001package ca.uhn.fhir.rest.server.interceptor.auth;
002
003/*
004 * #%L
005 * HAPI FHIR - Server Framework
006 * %%
007 * Copyright (C) 2014 - 2019 University Health Network
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 * http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.model.api.annotation.ResourceDef;
024import ca.uhn.fhir.model.primitive.IdDt;
025import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
026import ca.uhn.fhir.rest.api.server.RequestDetails;
027import com.google.common.collect.Lists;
028import org.apache.commons.lang3.Validate;
029import org.hl7.fhir.instance.model.api.IBaseResource;
030import org.hl7.fhir.instance.model.api.IIdType;
031
032import java.util.*;
033import java.util.concurrent.ConcurrentHashMap;
034
035import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
036
037public class RuleBuilder implements IAuthRuleBuilder {
038
039        private static final String[] EMPTY_STRING_ARRAY = new String[0];
040        private static final ConcurrentHashMap<Class<? extends IBaseResource>, String> ourTypeToName = new ConcurrentHashMap<>();
041        private ArrayList<IAuthRule> myRules;
042        private IAuthRuleBuilderRule myAllow;
043        private IAuthRuleBuilderRule myDeny;
044
045        public RuleBuilder() {
046                myRules = new ArrayList<>();
047        }
048
049        @Override
050        public IAuthRuleBuilderRule allow() {
051                if (myAllow == null) {
052                        myAllow = allow(null);
053                }
054                return myAllow;
055        }
056
057        @Override
058        public IAuthRuleBuilderRule allow(String theRuleName) {
059                return new RuleBuilderRule(PolicyEnum.ALLOW, theRuleName);
060        }
061
062        @Override
063        public IAuthRuleBuilderRuleOpClassifierFinished allowAll() {
064                return allowAll(null);
065        }
066
067        @Override
068        public IAuthRuleBuilderRuleOpClassifierFinished allowAll(String theRuleName) {
069                RuleImplOp rule = new RuleImplOp(theRuleName);
070                myRules.add(rule.setOp(RuleOpEnum.ALLOW_ALL));
071                return new RuleBuilderFinished(rule);
072        }
073
074        @Override
075        public List<IAuthRule> build() {
076                return myRules;
077        }
078
079        @Override
080        public IAuthRuleBuilderRule deny() {
081                if (myDeny == null) {
082                        myDeny = deny(null);
083                }
084                return myDeny;
085        }
086
087        @Override
088        public IAuthRuleBuilderRule deny(String theRuleName) {
089                return new RuleBuilderRule(PolicyEnum.DENY, theRuleName);
090        }
091
092        @Override
093        public IAuthRuleBuilderRuleOpClassifierFinished denyAll() {
094                return denyAll(null);
095        }
096
097        @Override
098        public IAuthRuleBuilderRuleOpClassifierFinished denyAll(String theRuleName) {
099                RuleImplOp rule = new RuleImplOp(theRuleName);
100                myRules.add(rule.setOp(RuleOpEnum.DENY_ALL));
101                return new RuleBuilderFinished(rule);
102        }
103
104        public interface ITenantApplicabilityChecker {
105                boolean applies(RequestDetails theRequest);
106        }
107
108        private class RuleBuilderFinished implements IAuthRuleFinished, IAuthRuleBuilderRuleOpClassifierFinished, IAuthRuleBuilderRuleOpClassifierFinishedWithTenantId {
109
110                protected final BaseRule myOpRule;
111                ITenantApplicabilityChecker myTenantApplicabilityChecker;
112                private List<IAuthRuleTester> myTesters;
113
114                RuleBuilderFinished(BaseRule theRule) {
115                        assert theRule != null;
116                        myOpRule = theRule;
117                }
118
119                @Override
120                public IAuthRuleBuilder andThen() {
121                        doBuildRule();
122                        return RuleBuilder.this;
123                }
124
125                @Override
126                public List<IAuthRule> build() {
127                        doBuildRule();
128                        return myRules;
129                }
130
131                /**
132                 * Subclasses may override
133                 */
134                protected void doBuildRule() {
135                        // nothing
136                }
137
138                @Override
139                public IAuthRuleBuilderRuleOpClassifierFinishedWithTenantId forTenantIds(String... theTenantIds) {
140                        return forTenantIds(Arrays.asList(defaultIfNull(theTenantIds, EMPTY_STRING_ARRAY)));
141                }
142
143                @Override
144                public IAuthRuleBuilderRuleOpClassifierFinishedWithTenantId forTenantIds(final Collection<String> theTenantIds) {
145                        setTenantApplicabilityChecker(theRequest -> theTenantIds.contains(theRequest.getTenantId()));
146                        return this;
147                }
148
149                List<IAuthRuleTester> getTesters() {
150                        if (myTesters == null) {
151                                return Collections.emptyList();
152                        }
153                        return myTesters;
154                }
155
156                @Override
157                public IAuthRuleBuilderRuleOpClassifierFinishedWithTenantId notForTenantIds(String... theTenantIds) {
158                        return notForTenantIds(Arrays.asList(defaultIfNull(theTenantIds, EMPTY_STRING_ARRAY)));
159                }
160
161                @Override
162                public IAuthRuleBuilderRuleOpClassifierFinishedWithTenantId notForTenantIds(final Collection<String> theTenantIds) {
163                        setTenantApplicabilityChecker(theRequest -> !theTenantIds.contains(theRequest.getTenantId()));
164                        return this;
165                }
166
167                private void setTenantApplicabilityChecker(ITenantApplicabilityChecker theTenantApplicabilityChecker) {
168                        myTenantApplicabilityChecker = theTenantApplicabilityChecker;
169                        myOpRule.setTenantApplicabilityChecker(myTenantApplicabilityChecker);
170                }
171
172                @Override
173                public IAuthRuleFinished withTester(IAuthRuleTester theTester) {
174                        if (myTesters == null) {
175                                myTesters = new ArrayList<>();
176                        }
177                        myTesters.add(theTester);
178                        myOpRule.addTester(theTester);
179
180                        return this;
181                }
182        }
183
184        private class RuleBuilderRule implements IAuthRuleBuilderRule {
185
186                private PolicyEnum myRuleMode;
187                private String myRuleName;
188                private RuleBuilderRuleOp myReadRuleBuilder;
189                private RuleBuilderRuleOp myWriteRuleBuilder;
190
191                RuleBuilderRule(PolicyEnum theRuleMode, String theRuleName) {
192                        myRuleMode = theRuleMode;
193                        myRuleName = theRuleName;
194                }
195
196                @Override
197                public IAuthRuleBuilderRuleConditional createConditional() {
198                        return new RuleBuilderRuleConditional(RestOperationTypeEnum.CREATE);
199                }
200
201                @Override
202                public IAuthRuleBuilderRuleOpDelete delete() {
203                        return new RuleBuilderRuleOp(RuleOpEnum.DELETE);
204                }
205
206                @Override
207                public IAuthRuleBuilderRuleConditional deleteConditional() {
208                        return new RuleBuilderRuleConditional(RestOperationTypeEnum.DELETE);
209                }
210
211                @Override
212                public RuleBuilderFinished metadata() {
213                        RuleImplOp rule = new RuleImplOp(myRuleName);
214                        rule.setOp(RuleOpEnum.METADATA);
215                        rule.setMode(myRuleMode);
216                        myRules.add(rule);
217                        return new RuleBuilderFinished(rule);
218                }
219
220                @Override
221                public IAuthRuleBuilderOperation operation() {
222                        return new RuleBuilderRuleOperation();
223                }
224
225                @Override
226                public IAuthRuleBuilderPatch patch() {
227                        return new PatchBuilder();
228                }
229
230                @Override
231                public IAuthRuleBuilderRuleOp read() {
232                        if (myReadRuleBuilder == null) {
233                                myReadRuleBuilder = new RuleBuilderRuleOp(RuleOpEnum.READ);
234                        }
235                        return myReadRuleBuilder;
236                }
237
238                @Override
239                public IAuthRuleBuilderRuleTransaction transaction() {
240                        return new RuleBuilderRuleTransaction();
241                }
242
243                @Override
244                public IAuthRuleBuilderRuleConditional updateConditional() {
245                        return new RuleBuilderRuleConditional(RestOperationTypeEnum.UPDATE);
246                }
247
248                @Override
249                public IAuthRuleBuilderRuleOp write() {
250                        if (myWriteRuleBuilder == null) {
251                                myWriteRuleBuilder = new RuleBuilderRuleOp(RuleOpEnum.WRITE);
252                        }
253                        return myWriteRuleBuilder;
254                }
255
256                @Override
257                public IAuthRuleBuilderRuleOp create() {
258                        if (myWriteRuleBuilder == null) {
259                                myWriteRuleBuilder = new RuleBuilderRuleOp(RuleOpEnum.CREATE);
260                        }
261                        return myWriteRuleBuilder;
262                }
263
264                @Override
265                public IAuthRuleBuilderGraphQL graphQL() {
266                        return new RuleBuilderGraphQL();
267                }
268
269                private class RuleBuilderRuleConditional implements IAuthRuleBuilderRuleConditional {
270
271                        private AppliesTypeEnum myAppliesTo;
272                        private Set<String> myAppliesToTypes;
273                        private RestOperationTypeEnum myOperationType;
274
275                        RuleBuilderRuleConditional(RestOperationTypeEnum theOperationType) {
276                                myOperationType = theOperationType;
277                        }
278
279                        @Override
280                        public IAuthRuleBuilderRuleConditionalClassifier allResources() {
281                                myAppliesTo = AppliesTypeEnum.ALL_RESOURCES;
282                                return new RuleBuilderRuleConditionalClassifier();
283                        }
284
285                        @Override
286                        public IAuthRuleBuilderRuleConditionalClassifier resourcesOfType(Class<? extends IBaseResource> theType) {
287                                Validate.notNull(theType, "theType must not be null");
288
289                                String typeName = toTypeName(theType);
290                                return resourcesOfType(typeName);
291                        }
292
293                        @Override
294                        public IAuthRuleBuilderRuleConditionalClassifier resourcesOfType(String theType) {
295                                myAppliesTo = AppliesTypeEnum.TYPES;
296                                myAppliesToTypes = Collections.singleton(theType);
297                                return new RuleBuilderRuleConditionalClassifier();
298                        }
299
300                        public class RuleBuilderRuleConditionalClassifier extends RuleBuilderFinished implements IAuthRuleBuilderRuleConditionalClassifier {
301
302                                RuleBuilderRuleConditionalClassifier() {
303                                        super(new RuleImplConditional(myRuleName));
304                                }
305
306                                @Override
307                                protected void doBuildRule() {
308                                        RuleImplConditional rule = (RuleImplConditional) myOpRule;
309                                        rule.setMode(myRuleMode);
310                                        rule.setOperationType(myOperationType);
311                                        rule.setAppliesTo(myAppliesTo);
312                                        rule.setAppliesToTypes(myAppliesToTypes);
313                                        rule.setTenantApplicabilityChecker(myTenantApplicabilityChecker);
314                                        rule.addTesters(getTesters());
315                                        myRules.add(rule);
316
317                                }
318                        }
319
320                }
321
322                private class RuleBuilderRuleOp implements IAuthRuleBuilderRuleOp, IAuthRuleBuilderRuleOpDelete {
323
324                        private final RuleOpEnum myRuleOp;
325                        private RuleBuilderRuleOpClassifier myInstancesBuilder;
326                        private boolean myOnCascade;
327
328                        RuleBuilderRuleOp(RuleOpEnum theRuleOp) {
329                                myRuleOp = theRuleOp;
330                        }
331
332                        @Override
333                        public IAuthRuleBuilderRuleOpClassifier allResources() {
334                                return new RuleBuilderRuleOpClassifier(AppliesTypeEnum.ALL_RESOURCES, null);
335                        }
336
337                        @Override
338                        public IAuthRuleFinished instance(String theId) {
339                                Validate.notBlank(theId, "theId must not be null or empty");
340                                return instance(new IdDt(theId));
341                        }
342
343                        @Override
344                        public IAuthRuleFinished instance(IIdType theId) {
345                                Validate.notNull(theId, "theId must not be null");
346                                Validate.notBlank(theId.getValue(), "theId.getValue() must not be null or empty");
347                                Validate.notBlank(theId.getIdPart(), "theId must contain an ID part");
348
349                                List<IIdType> instances = Lists.newArrayList(theId);
350                                return instances(instances);
351                        }
352
353                        @Override
354                        public RuleBuilderFinished instances(Collection<IIdType> theInstances) {
355                                Validate.notNull(theInstances, "theInstances must not be null");
356                                Validate.notEmpty(theInstances, "theInstances must not be empty");
357
358                                if (myInstancesBuilder == null) {
359                                        RuleBuilderRuleOpClassifier instancesBuilder = new RuleBuilderRuleOpClassifier(theInstances);
360                                        myInstancesBuilder = instancesBuilder;
361                                        return instancesBuilder.finished();
362                                } else {
363                                        return myInstancesBuilder.addInstances(theInstances);
364                                }
365                        }
366
367
368                        @Override
369                        public IAuthRuleBuilderRuleOpClassifier resourcesOfType(Class<? extends IBaseResource> theType) {
370                                Validate.notNull(theType, "theType must not be null");
371                                String resourceName = toTypeName(theType);
372                                return resourcesOfType(resourceName);
373                        }
374
375                        @Override
376                        public IAuthRuleBuilderRuleOpClassifier resourcesOfType(String theType) {
377                                Validate.notNull(theType, "theType must not be null");
378                                return new RuleBuilderRuleOpClassifier(AppliesTypeEnum.TYPES, Collections.singleton(theType));
379                        }
380
381                        @Override
382                        public IAuthRuleBuilderRuleOp onCascade() {
383                                myOnCascade = true;
384                                return this;
385                        }
386
387                        private class RuleBuilderRuleOpClassifier implements IAuthRuleBuilderRuleOpClassifier {
388
389                                private final AppliesTypeEnum myAppliesTo;
390                                private final Set<String> myAppliesToTypes;
391                                private ClassifierTypeEnum myClassifierType;
392                                private String myInCompartmentName;
393                                private Collection<? extends IIdType> myInCompartmentOwners;
394                                private Collection<IIdType> myAppliesToInstances;
395                                private RuleImplOp myRule;
396
397                                /**
398                                 * Constructor
399                                 */
400                                RuleBuilderRuleOpClassifier(AppliesTypeEnum theAppliesTo, Set<String> theAppliesToTypes) {
401                                        super();
402                                        myAppliesTo = theAppliesTo;
403                                        myAppliesToTypes = theAppliesToTypes;
404                                }
405
406                                /**
407                                 * Constructor
408                                 */
409                                RuleBuilderRuleOpClassifier(Collection<IIdType> theAppliesToInstances) {
410                                        myAppliesToInstances = theAppliesToInstances;
411                                        myAppliesTo = AppliesTypeEnum.INSTANCES;
412                                        myAppliesToTypes = null;
413                                }
414
415                                private RuleBuilderFinished finished() {
416                                        Validate.isTrue(myRule == null, "Can not call finished() twice");
417                                        myRule = new RuleImplOp(myRuleName);
418                                        myRule.setMode(myRuleMode);
419                                        myRule.setOp(myRuleOp);
420                                        myRule.setAppliesTo(myAppliesTo);
421                                        myRule.setAppliesToTypes(myAppliesToTypes);
422                                        myRule.setAppliesToInstances(myAppliesToInstances);
423                                        myRule.setClassifierType(myClassifierType);
424                                        myRule.setClassifierCompartmentName(myInCompartmentName);
425                                        myRule.setClassifierCompartmentOwners(myInCompartmentOwners);
426                                        myRule.setAppliesToDeleteCascade(myOnCascade);
427                                        myRules.add(myRule);
428
429                                        return new RuleBuilderFinished(myRule);
430                                }
431
432                                @Override
433                                public IAuthRuleBuilderRuleOpClassifierFinished inCompartment(String theCompartmentName, Collection<? extends IIdType> theOwners) {
434                                        Validate.notBlank(theCompartmentName, "theCompartmentName must not be null");
435                                        Validate.notNull(theOwners, "theOwners must not be null");
436                                        Validate.noNullElements(theOwners, "theOwners must not contain any null elements");
437                                        for (IIdType next : theOwners) {
438                                                validateOwner(next);
439                                        }
440                                        myInCompartmentName = theCompartmentName;
441                                        myInCompartmentOwners = theOwners;
442                                        myClassifierType = ClassifierTypeEnum.IN_COMPARTMENT;
443                                        return finished();
444                                }
445
446                                @Override
447                                public IAuthRuleBuilderRuleOpClassifierFinished inCompartment(String theCompartmentName, IIdType theOwner) {
448                                        Validate.notBlank(theCompartmentName, "theCompartmentName must not be null");
449                                        Validate.notNull(theOwner, "theOwner must not be null");
450                                        validateOwner(theOwner);
451                                        myInCompartmentName = theCompartmentName;
452                                        myInCompartmentOwners = Collections.singletonList(theOwner);
453                                        myClassifierType = ClassifierTypeEnum.IN_COMPARTMENT;
454                                        return finished();
455                                }
456
457                                private void validateOwner(IIdType theOwner) {
458                                        Validate.notBlank(theOwner.getIdPart(), "owner.getIdPart() must not be null or empty");
459                                        Validate.notBlank(theOwner.getIdPart(), "owner.getResourceType() must not be null or empty");
460                                }
461
462                                @Override
463                                public IAuthRuleBuilderRuleOpClassifierFinished withAnyId() {
464                                        myClassifierType = ClassifierTypeEnum.ANY_ID;
465                                        return finished();
466                                }
467
468                                RuleBuilderFinished addInstances(Collection<IIdType> theInstances) {
469                                        myAppliesToInstances.addAll(theInstances);
470                                        return new RuleBuilderFinished(myRule);
471                                }
472                        }
473
474                }
475
476                private class RuleBuilderRuleOperation implements IAuthRuleBuilderOperation {
477
478                        @Override
479                        public IAuthRuleBuilderOperationNamed named(String theOperationName) {
480                                Validate.notBlank(theOperationName, "theOperationName must not be null or empty");
481                                return new RuleBuilderRuleOperationNamed(theOperationName);
482                        }
483
484                        @Override
485                        public IAuthRuleBuilderOperationNamed withAnyName() {
486                                return new RuleBuilderRuleOperationNamed(null);
487                        }
488
489                        private class RuleBuilderRuleOperationNamed implements IAuthRuleBuilderOperationNamed {
490
491                                private String myOperationName;
492
493                                RuleBuilderRuleOperationNamed(String theOperationName) {
494                                        if (theOperationName != null && !theOperationName.startsWith("$")) {
495                                                myOperationName = '$' + theOperationName;
496                                        } else {
497                                                myOperationName = theOperationName;
498                                        }
499                                }
500
501                                private OperationRule createRule() {
502                                        OperationRule rule = new OperationRule(myRuleName);
503                                        rule.setOperationName(myOperationName);
504                                        rule.setMode(myRuleMode);
505                                        return rule;
506                                }
507
508                                @Override
509                                public IAuthRuleBuilderOperationNamedAndScoped onAnyInstance() {
510                                        OperationRule rule = createRule();
511                                        rule.appliesToAnyInstance();
512                                        return new RuleBuilderOperationNamedAndScoped(rule);
513                                }
514
515                                @Override
516                                public IAuthRuleBuilderOperationNamedAndScoped atAnyLevel() {
517                                        OperationRule rule = createRule();
518                                        rule.appliesAtAnyLevel(true);
519                                        return new RuleBuilderOperationNamedAndScoped(rule);
520                                }
521
522                                @Override
523                                public IAuthRuleBuilderOperationNamedAndScoped onAnyType() {
524                                        OperationRule rule = createRule();
525                                        rule.appliesToAnyType();
526                                        return new RuleBuilderOperationNamedAndScoped(rule);
527                                }
528
529                                @Override
530                                public IAuthRuleBuilderOperationNamedAndScoped onInstance(IIdType theInstanceId) {
531                                        Validate.notNull(theInstanceId, "theInstanceId must not be null");
532                                        Validate.notBlank(theInstanceId.getResourceType(), "theInstanceId does not have a resource type");
533                                        Validate.notBlank(theInstanceId.getIdPart(), "theInstanceId does not have an ID part");
534
535                                        OperationRule rule = createRule();
536                                        ArrayList<IIdType> ids = new ArrayList<>();
537                                        ids.add(theInstanceId);
538                                        rule.appliesToInstances(ids);
539                                        return new RuleBuilderOperationNamedAndScoped(rule);
540                                }
541
542                                @Override
543                                public IAuthRuleBuilderOperationNamedAndScoped onInstancesOfType(Class<? extends IBaseResource> theType) {
544                                        validateType(theType);
545
546                                        OperationRule rule = createRule();
547                                        rule.appliesToInstancesOfType(toTypeSet(theType));
548                                        return new RuleBuilderOperationNamedAndScoped(rule);
549                                }
550
551                                @Override
552                                public IAuthRuleBuilderOperationNamedAndScoped onServer() {
553                                        OperationRule rule = createRule();
554                                        rule.appliesToServer();
555                                        return new RuleBuilderOperationNamedAndScoped(rule);
556                                }
557
558                                @Override
559                                public IAuthRuleBuilderOperationNamedAndScoped onType(Class<? extends IBaseResource> theType) {
560                                        validateType(theType);
561
562                                        OperationRule rule = createRule();
563                                        rule.appliesToTypes(toTypeSet(theType));
564                                        return new RuleBuilderOperationNamedAndScoped(rule);
565                                }
566
567                                private HashSet<Class<? extends IBaseResource>> toTypeSet(Class<? extends IBaseResource> theType) {
568                                        HashSet<Class<? extends IBaseResource>> appliesToTypes = new HashSet<>();
569                                        appliesToTypes.add(theType);
570                                        return appliesToTypes;
571                                }
572
573                                private void validateType(Class<? extends IBaseResource> theType) {
574                                        Validate.notNull(theType, "theType must not be null");
575                                }
576
577                                private class RuleBuilderOperationNamedAndScoped implements IAuthRuleBuilderOperationNamedAndScoped {
578
579                                        private final OperationRule myRule;
580
581                                        RuleBuilderOperationNamedAndScoped(OperationRule theRule) {
582                                                myRule = theRule;
583                                        }
584
585                                        @Override
586                                        public IAuthRuleBuilderRuleOpClassifierFinished andAllowAllResponses() {
587                                                myRule.allowAllResponses();
588                                                myRules.add(myRule);
589                                                return new RuleBuilderFinished(myRule);
590                                        }
591
592                                        @Override
593                                        public IAuthRuleBuilderRuleOpClassifierFinished andRequireExplicitResponseAuthorization() {
594                                                myRules.add(myRule);
595                                                return new RuleBuilderFinished(myRule);
596                                        }
597                                }
598
599                        }
600
601                }
602
603                private class RuleBuilderRuleTransaction implements IAuthRuleBuilderRuleTransaction {
604
605                        @Override
606                        public IAuthRuleBuilderRuleTransactionOp withAnyOperation() {
607                                return new RuleBuilderRuleTransactionOp();
608                        }
609
610                        private class RuleBuilderRuleTransactionOp implements IAuthRuleBuilderRuleTransactionOp {
611
612                                @Override
613                                public IAuthRuleBuilderRuleOpClassifierFinished andApplyNormalRules() {
614                                        // Allow transaction
615                                        RuleImplOp rule = new RuleImplOp(myRuleName);
616                                        rule.setMode(myRuleMode);
617                                        rule.setOp(RuleOpEnum.TRANSACTION);
618                                        rule.setTransactionAppliesToOp(TransactionAppliesToEnum.ANY_OPERATION);
619                                        myRules.add(rule);
620                                        return new RuleBuilderFinished(rule);
621                                }
622
623                        }
624
625                }
626
627                private class PatchBuilder implements IAuthRuleBuilderPatch {
628
629                        PatchBuilder() {
630                                super();
631                        }
632
633                        @Override
634                        public IAuthRuleFinished allRequests() {
635                                BaseRule rule = new RuleImplPatch(myRuleName)
636                                        .setAllRequests(true)
637                                        .setMode(myRuleMode);
638                                myRules.add(rule);
639                                return new RuleBuilderFinished(rule);
640                        }
641                }
642
643                private class RuleBuilderGraphQL implements IAuthRuleBuilderGraphQL {
644                        @Override
645                        public IAuthRuleFinished any() {
646                                RuleImplOp rule = new RuleImplOp(myRuleName);
647                                rule.setOp(RuleOpEnum.GRAPHQL);
648                                rule.setMode(myRuleMode);
649                                myRules.add(rule);
650                                return new RuleBuilderFinished(rule);
651                        }
652                }
653        }
654
655        private static String toTypeName(Class<? extends IBaseResource> theType) {
656                String retVal = ourTypeToName.get(theType);
657                if (retVal == null) {
658                        ResourceDef resourceDef = theType.getAnnotation(ResourceDef.class);
659                        retVal = resourceDef.name();
660                        Validate.notBlank(retVal, "Could not determine resource type of class %s", theType);
661                        ourTypeToName.put(theType, retVal);
662                }
663                return retVal;
664        }
665
666}