// Path: fiat-core/src/main/java/com/netflix/spinnaker/fiat/model/resources/Permissions.java
// @ToString
// @EqualsAndHashCode
// public class Permissions {
// 
//   public static final Permissions EMPTY = Builder.fromMap(Collections.emptyMap());
// 
//   private final Map<Authorization, List<String>> permissions;
// 
//   private Permissions(Map<Authorization, List<String>> p) {
//     this.permissions = Collections.unmodifiableMap(p);
//   }
// 
//   /**
//    * Specifically here for Jackson deserialization. Sends data through the {@link Builder} in order
//    * to sanitize the input data (just in case).
//    */
//   @JsonCreator
//   public static Permissions factory(Map<Authorization, List<String>> data) {
//     return new Builder().set(data).build();
//   }
// 
//   /** Here specifically for Jackson serialization. */
//   @JsonValue
//   private Map<Authorization, List<String>> getPermissions() {
//     return permissions;
//   }
// 
//   public Set<String> allGroups() {
//     return permissions.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
//   }
// 
//   /**
//    * Determines whether this Permissions has any Authorizations with associated roles.
//    *
//    * @return whether this Permissions has any Authorizations with associated roles
//    * @deprecated check {@code !isRestricted()} instead
//    */
//   @Deprecated
//   public boolean isEmpty() {
//     return !isRestricted();
//   }
// 
//   public boolean isRestricted() {
//     return this.permissions.values().stream().anyMatch(groups -> !groups.isEmpty());
//   }
// 
//   public boolean isAuthorized(Set<Role> userRoles) {
//     return !getAuthorizations(userRoles).isEmpty();
//   }
// 
//   public Set<Authorization> getAuthorizations(Set<Role> userRoles) {
//     val r = userRoles.stream().map(Role::getName).collect(Collectors.toList());
//     return getAuthorizations(r);
//   }
// 
//   public Set<Authorization> getAuthorizations(List<String> userRoles) {
//     if (!isRestricted()) {
//       return Authorization.ALL;
//     }
// 
//     return this.permissions.entrySet().stream()
//         .filter(entry -> !Collections.disjoint(entry.getValue(), userRoles))
//         .map(Map.Entry::getKey)
//         .collect(Collectors.toSet());
//   }
// 
//   public List<String> get(Authorization a) {
//     return permissions.getOrDefault(a, new ArrayList<>());
//   }
// 
//   public Map<Authorization, List<String>> unpack() {
//     return Arrays.stream(Authorization.values()).collect(toMap(identity(), this::get));
//   }
// 
//   /**
//    * This is a helper class for setting up an immutable Permissions object. It also acts as the
//    * target Java Object for Spring's ConfigurationProperties deserialization.
//    *
//    * <p>Objects should be defined on the account config like:
//    *
//    * <p>someRoot: name: resourceName permissions: read: - role1 - role2 write: - role1
//    *
//    * <p>Group/Role names are trimmed of whitespace and lowercased.
//    */
//   public static class Builder extends LinkedHashMap<Authorization, List<String>> {
// 
//     private static Permissions fromMap(Map<Authorization, List<String>> authConfig) {
//       final Map<Authorization, List<String>> perms = new EnumMap<>(Authorization.class);
//       for (Authorization auth : Authorization.values()) {
//         Optional.ofNullable(authConfig.get(auth))
//             .map(
//                 groups ->
//                     groups.stream()
//                         .map(String::trim)
//                         .filter(s -> !s.isEmpty())
//                         .map(String::toLowerCase)
//                         .collect(Collectors.toList()))
//             .filter(g -> !g.isEmpty())
//             .map(Collections::unmodifiableList)
//             .ifPresent(roles -> perms.put(auth, roles));
//       }
//       return new Permissions(perms);
//     }
// 
//     @JsonCreator
//     public static Builder factory(Map<Authorization, List<String>> data) {
//       return new Builder().set(data);
//     }
// 
//     public Builder set(Map<Authorization, List<String>> p) {
//       this.clear();
//       this.putAll(p);
//       return this;
//     }
// 
//     public Builder add(Authorization a, String group) {
//       this.computeIfAbsent(a, ignored -> new ArrayList<>()).add(group);
//       return this;
//     }
// 
//     public Builder add(Authorization a, List<String> groups) {
//       groups.forEach(group -> add(a, group));
//       return this;
//     }
// 
//     public Permissions build() {
//       final Permissions result = fromMap(this);
//       if (!result.isRestricted()) {
//         return Permissions.EMPTY;
//       }
//       return result;
//     }
//   }
// }


import com.netflix.spinnaker.fiat.model.resources.Permissions;
import com.netflix.spinnaker.fiat.model.resources.Resource;
import javax.annotation.Nonnull;
/*
 * Copyright 2019 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.netflix.spinnaker.fiat.providers;


/**
 * A ResourcePermissionSource is capable of resolving the Permissions for a specified Resource from
 * a specified single source.
 *
 * <p>Note that while the API signature matches ResourcePermissionProvider the intent of
 * ResourcePermissionSource is to model a single source of Permissions (for example CloudDriver as a
 * source of Account permissions), while ResourcePermissionProvider is responsible for supplying the
 * computed Permission considering all available ResourcePermissionSources.
 *
 * @param <T> the type of Resource this ResourcePermissionSource will supply Permissions for
 */
public interface ResourcePermissionSource<T extends Resource> {

  /**
   * Retrieves Permissions for the supplied resource.
   *
   * @param resource the resource for which to get permissions (never null)
   * @return the Permissions for the resource (never null - use Permissions.EMPTY or apply some
   *     restriction)
   */
  @Nonnull
// Path: fiat-core/src/main/java/com/netflix/spinnaker/fiat/model/resources/Permissions.java
// @ToString
// @EqualsAndHashCode
// public class Permissions {
// 
//   public static final Permissions EMPTY = Builder.fromMap(Collections.emptyMap());
// 
//   private final Map<Authorization, List<String>> permissions;
// 
//   private Permissions(Map<Authorization, List<String>> p) {
//     this.permissions = Collections.unmodifiableMap(p);
//   }
// 
//   /**
//    * Specifically here for Jackson deserialization. Sends data through the {@link Builder} in order
//    * to sanitize the input data (just in case).
//    */
//   @JsonCreator
//   public static Permissions factory(Map<Authorization, List<String>> data) {
//     return new Builder().set(data).build();
//   }
// 
//   /** Here specifically for Jackson serialization. */
//   @JsonValue
//   private Map<Authorization, List<String>> getPermissions() {
//     return permissions;
//   }
// 
//   public Set<String> allGroups() {
//     return permissions.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
//   }
// 
//   /**
//    * Determines whether this Permissions has any Authorizations with associated roles.
//    *
//    * @return whether this Permissions has any Authorizations with associated roles
//    * @deprecated check {@code !isRestricted()} instead
//    */
//   @Deprecated
//   public boolean isEmpty() {
//     return !isRestricted();
//   }
// 
//   public boolean isRestricted() {
//     return this.permissions.values().stream().anyMatch(groups -> !groups.isEmpty());
//   }
// 
//   public boolean isAuthorized(Set<Role> userRoles) {
//     return !getAuthorizations(userRoles).isEmpty();
//   }
// 
//   public Set<Authorization> getAuthorizations(Set<Role> userRoles) {
//     val r = userRoles.stream().map(Role::getName).collect(Collectors.toList());
//     return getAuthorizations(r);
//   }
// 
//   public Set<Authorization> getAuthorizations(List<String> userRoles) {
//     if (!isRestricted()) {
//       return Authorization.ALL;
//     }
// 
//     return this.permissions.entrySet().stream()
//         .filter(entry -> !Collections.disjoint(entry.getValue(), userRoles))
//         .map(Map.Entry::getKey)
//         .collect(Collectors.toSet());
//   }
// 
//   public List<String> get(Authorization a) {
//     return permissions.getOrDefault(a, new ArrayList<>());
//   }
// 
//   public Map<Authorization, List<String>> unpack() {
//     return Arrays.stream(Authorization.values()).collect(toMap(identity(), this::get));
//   }
// 
//   /**
//    * This is a helper class for setting up an immutable Permissions object. It also acts as the
//    * target Java Object for Spring's ConfigurationProperties deserialization.
//    *
//    * <p>Objects should be defined on the account config like:
//    *
//    * <p>someRoot: name: resourceName permissions: read: - role1 - role2 write: - role1
//    *
//    * <p>Group/Role names are trimmed of whitespace and lowercased.
//    */
//   public static class Builder extends LinkedHashMap<Authorization, List<String>> {
// 
//     private static Permissions fromMap(Map<Authorization, List<String>> authConfig) {
//       final Map<Authorization, List<String>> perms = new EnumMap<>(Authorization.class);
//       for (Authorization auth : Authorization.values()) {
//         Optional.ofNullable(authConfig.get(auth))
//             .map(
//                 groups ->
//                     groups.stream()
//                         .map(String::trim)
//                         .filter(s -> !s.isEmpty())
//                         .map(String::toLowerCase)
//                         .collect(Collectors.toList()))
//             .filter(g -> !g.isEmpty())
//             .map(Collections::unmodifiableList)
//             .ifPresent(roles -> perms.put(auth, roles));
//       }
//       return new Permissions(perms);
//     }
// 
//     @JsonCreator
//     public static Builder factory(Map<Authorization, List<String>> data) {
//       return new Builder().set(data);
//     }
// 
//     public Builder set(Map<Authorization, List<String>> p) {
//       this.clear();
//       this.putAll(p);
//       return this;
//     }
// 
//     public Builder add(Authorization a, String group) {
//       this.computeIfAbsent(a, ignored -> new ArrayList<>()).add(group);
//       return this;
//     }
// 
//     public Builder add(Authorization a, List<String> groups) {
//       groups.forEach(group -> add(a, group));
//       return this;
//     }
// 
//     public Permissions build() {
//       final Permissions result = fromMap(this);
//       if (!result.isRestricted()) {
//         return Permissions.EMPTY;
//       }
//       return result;
//     }
//   }
// }


// Path: fiat-roles/src/main/java/com/netflix/spinnaker/fiat/providers/ResourcePermissionSource.java
import com.netflix.spinnaker.fiat.model.resources.Permissions;
import com.netflix.spinnaker.fiat.model.resources.Resource;
import javax.annotation.Nonnull;

/*
 * Copyright 2019 Netflix, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.netflix.spinnaker.fiat.providers;


/**
 * A ResourcePermissionSource is capable of resolving the Permissions for a specified Resource from
 * a specified single source.
 *
 * <p>Note that while the API signature matches ResourcePermissionProvider the intent of
 * ResourcePermissionSource is to model a single source of Permissions (for example CloudDriver as a
 * source of Account permissions), while ResourcePermissionProvider is responsible for supplying the
 * computed Permission considering all available ResourcePermissionSources.
 *
 * @param <T> the type of Resource this ResourcePermissionSource will supply Permissions for
 */
public interface ResourcePermissionSource<T extends Resource> {

  /**
   * Retrieves Permissions for the supplied resource.
   *
   * @param resource the resource for which to get permissions (never null)
   * @return the Permissions for the resource (never null - use Permissions.EMPTY or apply some
   *     restriction)
   */
  @Nonnull
  Permissions getPermissions(@Nonnull T resource);