parseSchemaFromAlterOperation parses the string schema given in input operation to a Go struct, and performs some checks to make sure that the schema is valid.
(ctx context.Context, sch string)
| 234 | // parseSchemaFromAlterOperation parses the string schema given in input operation to a Go |
| 235 | // struct, and performs some checks to make sure that the schema is valid. |
| 236 | func parseSchemaFromAlterOperation(ctx context.Context, sch string) ( |
| 237 | *schema.ParsedSchema, error) { |
| 238 | |
| 239 | // If a background task is already running, we should reject all the new alter requests. |
| 240 | if schema.State().IndexingInProgress() { |
| 241 | return nil, errIndexingInProgress |
| 242 | } |
| 243 | |
| 244 | namespace, err := x.ExtractNamespace(ctx) |
| 245 | if err != nil { |
| 246 | return nil, errors.Wrapf(err, "While parsing schema") |
| 247 | } |
| 248 | |
| 249 | if x.IsRootNsOperation(ctx) { |
| 250 | // Only the guardian of the galaxy can do a galaxy wide query/mutation. This operation is |
| 251 | // needed by live loader. |
| 252 | if err := AuthSuperAdmin(ctx); err != nil { |
| 253 | s := status.Convert(err) |
| 254 | return nil, status.Error(s.Code(), |
| 255 | "Non superadmin user cannot bypass namespaces. "+s.Message()) |
| 256 | } |
| 257 | var err error |
| 258 | namespace, err = strconv.ParseUint(x.GetForceNamespace(ctx), 0, 64) |
| 259 | if err != nil { |
| 260 | return nil, errors.Wrapf(err, "Valid force namespace not found in metadata") |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | result, err := schema.ParseWithNamespace(sch, namespace) |
| 265 | if err != nil { |
| 266 | return nil, err |
| 267 | } |
| 268 | |
| 269 | preds := make(map[string]struct{}) |
| 270 | for _, update := range result.Preds { |
| 271 | if _, ok := preds[update.Predicate]; ok { |
| 272 | return nil, errors.Errorf("predicate %s defined multiple times", x.ParseAttr(update.Predicate)) |
| 273 | } |
| 274 | preds[update.Predicate] = struct{}{} |
| 275 | |
| 276 | // Pre-defined predicates cannot be altered but let the update go through |
| 277 | // if the update is equal to the existing one. |
| 278 | if schema.CheckAndModifyPreDefPredicate(update) { |
| 279 | return nil, errors.Errorf("predicate %s is pre-defined and is not allowed to be"+ |
| 280 | " modified", x.ParseAttr(update.Predicate)) |
| 281 | } |
| 282 | |
| 283 | if err := validatePredName(update.Predicate); err != nil { |
| 284 | return nil, err |
| 285 | } |
| 286 | // Users are not allowed to create a predicate under the reserved `dgraph.` namespace. But, |
| 287 | // there are pre-defined predicates (subset of reserved predicates), and for them we allow |
| 288 | // the schema update to go through if the update is equal to the existing one. |
| 289 | // So, here we check if the predicate is reserved but not pre-defined to block users from |
| 290 | // creating predicates in reserved namespace. A predicate owned by a registered |
| 291 | // ReservedNamespace (see x.RegisterReservedNamespace) is allowed through, so a plugin can |
| 292 | // create its own predicates under `dgraph.` at runtime. |
| 293 | if x.IsReservedPredicate(update.Predicate) && |