github.com/dolthub/go-mysql-server@v0.18.0/sql/mysql_db/tables_priv.go (about) 1 // Copyright 2022 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package mysql_db 16 17 import ( 18 "fmt" 19 "strings" 20 "sync" 21 "time" 22 23 "github.com/dolthub/vitess/go/sqltypes" 24 25 "github.com/dolthub/go-mysql-server/sql" 26 "github.com/dolthub/go-mysql-server/sql/expression" 27 "github.com/dolthub/go-mysql-server/sql/in_mem_table" 28 "github.com/dolthub/go-mysql-server/sql/types" 29 ) 30 31 const tablesPrivTblName = "tables_priv" 32 33 var ( 34 errTablesPrivEntry = fmt.Errorf("the converter for the `tables_priv` table was given an unknown entry") 35 errTablesPrivRow = fmt.Errorf("the converter for the `tables_priv` table was given a row belonging to an unknown schema") 36 37 tablesPrivTblSchema sql.Schema 38 ) 39 40 func UserAddTablesRow(ctx *sql.Context, row sql.Row, user *User) (*User, error) { 41 if len(row) != len(tablesPrivTblSchema) { 42 return nil, errTablesPrivRow 43 } 44 45 dbName, ok := row[tablesPrivTblColIndex_Db].(string) 46 if !ok { 47 return nil, errTablesPrivRow 48 } 49 tblName, ok := row[tablesPrivTblColIndex_Table_name].(string) 50 if !ok { 51 return nil, errTablesPrivRow 52 } 53 tablePrivs, ok := row[tablesPrivTblColIndex_Table_priv].(uint64) 54 if !ok { 55 return nil, errTablesPrivRow 56 } 57 tablePrivStrs, err := tablesPrivTblSchema[tablesPrivTblColIndex_Table_priv].Type.(sql.SetType).BitsToString(tablePrivs) 58 if err != nil { 59 return nil, err 60 } 61 62 user = UserCopy(user) 63 64 var privs []sql.PrivilegeType 65 for _, val := range strings.Split(tablePrivStrs, ",") { 66 switch val { 67 case "Select": 68 privs = append(privs, sql.PrivilegeType_Select) 69 case "Insert": 70 privs = append(privs, sql.PrivilegeType_Insert) 71 case "Update": 72 privs = append(privs, sql.PrivilegeType_Update) 73 case "Delete": 74 privs = append(privs, sql.PrivilegeType_Delete) 75 case "Create": 76 privs = append(privs, sql.PrivilegeType_Create) 77 case "Drop": 78 privs = append(privs, sql.PrivilegeType_Drop) 79 case "Grant": 80 privs = append(privs, sql.PrivilegeType_GrantOption) 81 case "References": 82 privs = append(privs, sql.PrivilegeType_References) 83 case "Index": 84 privs = append(privs, sql.PrivilegeType_Index) 85 case "Alter": 86 privs = append(privs, sql.PrivilegeType_Alter) 87 case "Create View": 88 privs = append(privs, sql.PrivilegeType_CreateView) 89 case "Show view": 90 privs = append(privs, sql.PrivilegeType_ShowView) 91 case "Trigger": 92 privs = append(privs, sql.PrivilegeType_Trigger) 93 case "": 94 default: 95 return nil, errTablesPrivRow 96 } 97 } 98 user.PrivilegeSet.AddTable(dbName, tblName, privs...) 99 return user, nil 100 } 101 102 func UserRemoveTablesRow(ctx *sql.Context, row sql.Row, user *User) (*User, error) { 103 if len(row) != len(tablesPrivTblSchema) { 104 return nil, errTablesPrivRow 105 } 106 107 db, ok := row[tablesPrivTblColIndex_Db].(string) 108 if !ok { 109 return nil, errTablesPrivRow 110 } 111 tbl, ok := row[tablesPrivTblColIndex_Table_name].(string) 112 if !ok { 113 return nil, errTablesPrivRow 114 } 115 116 user = UserCopy(user) 117 user.PrivilegeSet.ClearTable(db, tbl) 118 return user, nil 119 } 120 121 func UserFromTablesRow(ctx *sql.Context, row sql.Row) (*User, error) { 122 if len(row) != len(tablesPrivTblSchema) { 123 return nil, errTablesPrivRow 124 } 125 host, ok := row[tablesPrivTblColIndex_Host].(string) 126 if !ok { 127 return nil, errTablesPrivRow 128 } 129 user, ok := row[tablesPrivTblColIndex_User].(string) 130 if !ok { 131 return nil, errTablesPrivRow 132 } 133 return &User{ 134 Host: host, 135 User: user, 136 }, nil 137 } 138 139 func UserToTablesRows(ctx *sql.Context, user *User) ([]sql.Row, error) { 140 newRow := func() (sql.Row, error) { 141 row := make(sql.Row, len(tablesPrivTblSchema)) 142 var err error 143 for i, col := range tablesPrivTblSchema { 144 row[i], err = col.Default.Eval(ctx, nil) 145 if err != nil { 146 return nil, err // Should never happen, schema is static 147 } 148 } 149 return row, nil 150 } 151 152 var rows []sql.Row 153 for _, dbSet := range user.PrivilegeSet.GetDatabases() { 154 for _, tblSet := range dbSet.GetTables() { 155 if tblSet.Count() == 0 { 156 continue 157 } 158 row, err := newRow() 159 if err != nil { 160 return nil, err 161 } 162 163 row[tablesPrivTblColIndex_User] = user.User 164 row[tablesPrivTblColIndex_Host] = user.Host 165 row[tablesPrivTblColIndex_Db] = dbSet.Name() 166 row[tablesPrivTblColIndex_Table_name] = tblSet.Name() 167 168 var privs []string 169 for _, priv := range tblSet.ToSlice() { 170 switch priv { 171 case sql.PrivilegeType_Select: 172 privs = append(privs, "Select") 173 case sql.PrivilegeType_Insert: 174 privs = append(privs, "Insert") 175 case sql.PrivilegeType_Update: 176 privs = append(privs, "Update") 177 case sql.PrivilegeType_Delete: 178 privs = append(privs, "Delete") 179 case sql.PrivilegeType_Create: 180 privs = append(privs, "Create") 181 case sql.PrivilegeType_Drop: 182 privs = append(privs, "Drop") 183 case sql.PrivilegeType_GrantOption: 184 privs = append(privs, "Grant") 185 case sql.PrivilegeType_References: 186 privs = append(privs, "References") 187 case sql.PrivilegeType_Index: 188 privs = append(privs, "Index") 189 case sql.PrivilegeType_Alter: 190 privs = append(privs, "Alter") 191 case sql.PrivilegeType_CreateView: 192 privs = append(privs, "Create View") 193 case sql.PrivilegeType_ShowView: 194 privs = append(privs, "Show view") 195 case sql.PrivilegeType_Trigger: 196 privs = append(privs, "Trigger") 197 } 198 } 199 formattedSet, _, err := tablesPrivTblSchema[tablesPrivTblColIndex_Table_priv].Type.Convert(strings.Join(privs, ",")) 200 if err != nil { 201 return nil, err 202 } 203 row[tablesPrivTblColIndex_Table_priv] = formattedSet.(uint64) 204 rows = append(rows, row) 205 } 206 } 207 208 return rows, nil 209 } 210 211 func NewUserTablesIndexedSetTable(set in_mem_table.IndexedSet[*User], lock, rlock sync.Locker) *in_mem_table.MultiIndexedSetTable[*User] { 212 table := in_mem_table.NewMultiIndexedSetTable[*User]( 213 tablesPrivTblName, 214 tablesPrivTblSchema, 215 sql.Collation_utf8mb3_bin, 216 set, 217 in_mem_table.MultiValueOps[*User]{ 218 ToRows: UserToTablesRows, 219 FromRow: UserFromTablesRow, 220 AddRow: UserAddTablesRow, 221 DeleteRow: UserRemoveTablesRow, 222 }, 223 lock, 224 rlock, 225 ) 226 return table 227 } 228 229 // init creates the schema for the "tables_priv" Grant Table. 230 func init() { 231 // Types 232 char32_utf8_bin := types.MustCreateString(sqltypes.Char, 32, sql.Collation_utf8_bin) 233 char64_utf8_bin := types.MustCreateString(sqltypes.Char, 64, sql.Collation_utf8_bin) 234 char255_ascii_general_ci := types.MustCreateString(sqltypes.Char, 255, sql.Collation_ascii_general_ci) 235 set_ColumnPrivs_utf8_general_ci := types.MustCreateSetType([]string{"Select", "Insert", "Update", "References"}, sql.Collation_utf8_general_ci) 236 set_TablePrivs_utf8_general_ci := types.MustCreateSetType([]string{ 237 "Select", "Insert", "Update", "Delete", "Create", "Drop", "Grant", 238 "References", "Index", "Alter", "Create View", "Show view", "Trigger"}, sql.Collation_utf8_general_ci) 239 varchar288_utf8_bin := types.MustCreateString(sqltypes.VarChar, 288, sql.Collation_utf8_bin) 240 241 // Column Templates 242 char32_utf8_bin_not_null_default_empty := &sql.Column{ 243 Type: char32_utf8_bin, 244 Default: mustDefault(expression.NewLiteral("", char32_utf8_bin), char32_utf8_bin, true, false), 245 Nullable: false, 246 } 247 char64_utf8_bin_not_null_default_empty := &sql.Column{ 248 Type: char64_utf8_bin, 249 Default: mustDefault(expression.NewLiteral("", char64_utf8_bin), char64_utf8_bin, true, false), 250 Nullable: false, 251 } 252 char255_ascii_general_ci_not_null_default_empty := &sql.Column{ 253 Type: char255_ascii_general_ci, 254 Default: mustDefault(expression.NewLiteral("", char255_ascii_general_ci), char255_ascii_general_ci, true, false), 255 Nullable: false, 256 } 257 set_ColumnPrivs_utf8_general_ci_not_null_default_empty := &sql.Column{ 258 Type: set_ColumnPrivs_utf8_general_ci, 259 Default: mustDefault(expression.NewLiteral("", set_ColumnPrivs_utf8_general_ci), set_ColumnPrivs_utf8_general_ci, true, false), 260 Nullable: false, 261 } 262 set_TablePrivs_utf8_general_ci_not_null_default_empty := &sql.Column{ 263 Type: set_TablePrivs_utf8_general_ci, 264 Default: mustDefault(expression.NewLiteral("", set_TablePrivs_utf8_general_ci), set_TablePrivs_utf8_general_ci, true, false), 265 Nullable: false, 266 } 267 timestamp_not_null_default_epoch := &sql.Column{ 268 Type: types.Timestamp, 269 Default: mustDefault(expression.NewLiteral(time.Unix(1, 0).UTC(), types.Timestamp), types.Timestamp, true, false), 270 Nullable: false, 271 } 272 varchar288_utf8_bin_not_null_default_empty := &sql.Column{ 273 Type: varchar288_utf8_bin, 274 Default: mustDefault(expression.NewLiteral("", varchar288_utf8_bin), varchar288_utf8_bin, true, false), 275 Nullable: false, 276 } 277 278 tablesPrivTblSchema = sql.Schema{ 279 columnTemplate("Host", tablesPrivTblName, true, char255_ascii_general_ci_not_null_default_empty), 280 columnTemplate("Db", tablesPrivTblName, true, char64_utf8_bin_not_null_default_empty), 281 columnTemplate("User", tablesPrivTblName, true, char32_utf8_bin_not_null_default_empty), 282 columnTemplate("Table_name", tablesPrivTblName, true, char64_utf8_bin_not_null_default_empty), 283 columnTemplate("Grantor", tablesPrivTblName, false, varchar288_utf8_bin_not_null_default_empty), 284 columnTemplate("Timestamp", tablesPrivTblName, false, timestamp_not_null_default_epoch), 285 columnTemplate("Table_priv", tablesPrivTblName, false, set_TablePrivs_utf8_general_ci_not_null_default_empty), 286 columnTemplate("Column_priv", tablesPrivTblName, false, set_ColumnPrivs_utf8_general_ci_not_null_default_empty), 287 } 288 } 289 290 // These represent the column indexes of the "tables_priv" Grant Table. 291 const ( 292 tablesPrivTblColIndex_Host int = iota 293 tablesPrivTblColIndex_Db 294 tablesPrivTblColIndex_User 295 tablesPrivTblColIndex_Table_name 296 tablesPrivTblColIndex_Grantor 297 tablesPrivTblColIndex_Timestamp 298 tablesPrivTblColIndex_Table_priv 299 tablesPrivTblColIndex_Column_priv 300 )