code: func validateGrants(ctx *validation.Context, gs []*messages.Acl) {
  	for _, g := range gs {
  		switch {
  		case g.GetRole() != messages.Acl_OWNER && g.GetRole() != messages.Acl_READER && g.GetRole() != messages.Acl_TRIGGERER:
  			ctx.Errorf("invalid role %q", g.GetRole())
  		case g.GetGrantedTo() == "":
  			ctx.Errorf("missing granted_to for role %s", g.GetRole())
  		case strings.HasPrefix(g.GetGrantedTo(), "group:"):
  			if g.GetGrantedTo()[len("group:"):] == "" {
  				ctx.Errorf("invalid granted_to %q for role %s: needs a group name", g.GetGrantedTo(), g.GetRole())
  			}
  		default:
  			id := g.GetGrantedTo()
  			if !strings.ContainsRune(g.GetGrantedTo(), ':') {
  				id = "user:" + g.GetGrantedTo()
  			}
  			if _, err := identity.MakeIdentity(id); err != nil {
  				ctx.Error(errors.Annotate(err, "invalid granted_to %q for role %s", g.GetGrantedTo(), g.GetRole()).Err())
  			}
  		}
  	}
  }
docs: // validateGrants validates the fields of the provided grants.
  //
  // Errors are returned via validation.Context.