| Michael Hanl | deb3c21 | 2015-10-16 23:02:24 +0200 | [diff] [blame^] | 1 | package de.ids_mannheim.korap.security.ac; |
| 2 | |
| 3 | import de.ids_mannheim.korap.ext.resource.KorAPResource; |
| 4 | import de.ids_mannheim.korap.ext.resource.ResourceFactory; |
| 5 | import de.ids_mannheim.korap.ext.security.types.PolicyCondition; |
| 6 | import de.ids_mannheim.korap.ext.security.types.PolicyContext; |
| 7 | import de.ids_mannheim.korap.ext.security.types.SecurityPolicy; |
| 8 | import de.ids_mannheim.korap.user.User; |
| 9 | import de.ids_mannheim.korap.utils.PrefixTreeMap; |
| 10 | import lombok.Data; |
| 11 | import org.springframework.dao.DataAccessException; |
| 12 | import org.springframework.jdbc.core.ResultSetExtractor; |
| 13 | import org.springframework.jdbc.core.RowMapper; |
| 14 | |
| 15 | import java.sql.ResultSet; |
| 16 | import java.sql.SQLException; |
| 17 | import java.sql.Timestamp; |
| 18 | import java.util.*; |
| 19 | |
| 20 | /** |
| 21 | * @author hanl |
| 22 | * @date 03/03/2014 |
| 23 | */ |
| 24 | public class SecurityRowMappers { |
| 25 | |
| 26 | public static class PolicyRowMapper implements RowMapper<SecurityPolicy> { |
| 27 | |
| 28 | @Override |
| 29 | public SecurityPolicy mapRow(ResultSet rs, int rowNum) |
| 30 | throws SQLException { |
| 31 | SecurityPolicy p = new SecurityPolicy(); |
| 32 | p.setID(rs.getInt("pid")).setTarget(rs.getString("persistent_id")) |
| 33 | .setPOSIX(rs.getString("perm")); |
| 34 | |
| 35 | PolicyContext context = new PolicyContext(); |
| 36 | context.setIPMask(rs.getString("iprange")); |
| 37 | Timestamp date = rs.getTimestamp("enable"); |
| 38 | Timestamp date2 = rs.getTimestamp("expire"); |
| 39 | if (date != null) |
| 40 | context.setEnableTime(date.getTime()); |
| 41 | if (date2 != null) |
| 42 | context.setExpirationTime(date2.getTime()); |
| 43 | // context.addFlag("export", rs.getBoolean("export")); |
| 44 | // context.addFlag("sym_use", rs.getInt("sym_use")); |
| 45 | p.setContext(context); |
| 46 | return p; |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | @Data |
| 51 | public static class FlagContext extends PolicyContext { |
| 52 | |
| 53 | private Map<String, Object> flags; |
| 54 | |
| 55 | public FlagContext() { |
| 56 | this.flags = new HashMap<>(); |
| 57 | } |
| 58 | |
| 59 | public FlagContext addFlag(String key, Object value) { |
| 60 | this.flags.put(key, value); |
| 61 | return this; |
| 62 | } |
| 63 | |
| 64 | public FlagContext removeFlag(String key) { |
| 65 | this.flags.remove(key); |
| 66 | return this; |
| 67 | } |
| 68 | |
| 69 | public FlagContext clearFlags() { |
| 70 | this.flags.clear(); |
| 71 | return this; |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | public static List<SecurityPolicy>[] mapping(ResultSet rs, User user) |
| 76 | throws SQLException { |
| 77 | List<SecurityPolicy>[] policyArray = null; |
| 78 | List<Integer>[] idx = null; |
| 79 | while (rs.next()) { |
| 80 | // user has no permission here --> thus skip |
| 81 | if (rs.getInt("allowed") == 0) |
| 82 | continue; |
| 83 | |
| 84 | if (policyArray == null) { |
| 85 | int v = rs.getInt("max_depth") + 1; |
| 86 | policyArray = new List[v]; |
| 87 | idx = new List[v]; |
| 88 | } |
| 89 | |
| 90 | int depth = rs.getInt("depth"); |
| 91 | |
| 92 | if (policyArray[depth] == null) { |
| 93 | policyArray[depth] = new ArrayList<>(); |
| 94 | idx[depth] = new ArrayList<>(); |
| 95 | } |
| 96 | |
| 97 | Integer pid = rs.getInt("pid"); |
| 98 | String grouping = rs.getString("group_ref"); |
| 99 | Integer index = idx[depth].indexOf(pid); |
| 100 | |
| 101 | SecurityPolicy policy; |
| 102 | if (index == -1) { |
| 103 | if (pid == -1 && grouping.equalsIgnoreCase("self")) { |
| 104 | policy = new SecurityPolicy.OwnerPolicy( |
| 105 | rs.getString("persistent_id"), rs.getInt("creator")); |
| 106 | policyArray[depth].add(0, policy); |
| 107 | idx[depth].add(0, pid); |
| 108 | }else { |
| 109 | policy = new SecurityRowMappers.PolicyRowMapper() |
| 110 | .mapRow(rs, 0); |
| 111 | policyArray[depth].add(policy); |
| 112 | idx[depth].add(pid); |
| 113 | |
| 114 | //todo: |
| 115 | // if (policy.isActive(user)) { |
| 116 | // policyArray[depth].add(policy); |
| 117 | // idx[depth].add(pid); |
| 118 | // } |
| 119 | } |
| 120 | }else |
| 121 | policy = policyArray[depth].get(index); |
| 122 | |
| 123 | PolicyCondition c = new PolicyCondition(rs.getString("group_ref")); |
| 124 | if (!policy.contains(c)) |
| 125 | policy.addCondition(c); |
| 126 | } |
| 127 | return policyArray; |
| 128 | } |
| 129 | |
| 130 | @Deprecated |
| 131 | public static List<SecurityPolicy>[] map(ResultSet rs) throws SQLException { |
| 132 | Map<Integer, SecurityPolicy>[] policyArray = null; |
| 133 | while (rs.next()) { |
| 134 | // user has no permission here! |
| 135 | if (rs.getInt("allowed") == 0) |
| 136 | continue; |
| 137 | |
| 138 | if (policyArray == null) |
| 139 | policyArray = new Map[rs.getInt("max_depth") + 1]; |
| 140 | |
| 141 | int depth = rs.getInt("depth"); |
| 142 | Map<Integer, SecurityPolicy> cursor = policyArray[depth]; |
| 143 | if (cursor == null) |
| 144 | cursor = new HashMap<>(); |
| 145 | |
| 146 | Integer pid = rs.getInt("pid"); |
| 147 | SecurityPolicy policy = cursor.get(pid); |
| 148 | if (policy == null) { |
| 149 | policy = new SecurityRowMappers.PolicyRowMapper().mapRow(rs, 0); |
| 150 | cursor.put(pid, policy); |
| 151 | } |
| 152 | PolicyCondition c = new PolicyCondition(rs.getString("group_ref")); |
| 153 | |
| 154 | if (!policy.contains(c)) |
| 155 | policy.addCondition(c); |
| 156 | } |
| 157 | |
| 158 | List<SecurityPolicy>[] results; |
| 159 | if (policyArray == null) { |
| 160 | results = new List[1]; |
| 161 | results[0] = new ArrayList<>(); |
| 162 | }else { |
| 163 | results = new List[policyArray.length]; |
| 164 | for (int idx = 0; idx < policyArray.length; idx++) { |
| 165 | if (policyArray[idx] != null) |
| 166 | results[idx] = new ArrayList<>(policyArray[idx].values()); |
| 167 | else |
| 168 | results[idx] = new ArrayList<>(); |
| 169 | } |
| 170 | } |
| 171 | return results; |
| 172 | } |
| 173 | |
| 174 | public static class HierarchicalResultExtractor |
| 175 | implements ResultSetExtractor<List<KorAPResource.Container>> { |
| 176 | |
| 177 | private boolean _withpid; |
| 178 | |
| 179 | // public HierarchicalResultExtractor(boolean wpid) { |
| 180 | // this._withpid = wpid; |
| 181 | // } |
| 182 | |
| 183 | // todo: in order for this to work, all parent flags need to be matched in sql! |
| 184 | public List<KorAPResource.Container> extractData(ResultSet rs) |
| 185 | throws SQLException, DataAccessException { |
| 186 | // contains the container with the highest available name_path to retrieve partial matches! |
| 187 | PrefixTreeMap<KorAPResource.Container[]> containerMap = new PrefixTreeMap<>(); |
| 188 | Map<Integer, SecurityPolicy> trace = new HashMap<>(); |
| 189 | |
| 190 | while (rs.next()) { |
| 191 | KorAPResource.Container[] cursor; |
| 192 | Integer pid = rs.getInt("pid"); |
| 193 | |
| 194 | SecurityPolicy policy = trace.get(pid); |
| 195 | if (policy == null | pid == -1) { |
| 196 | // Integer id = rs.getInt("id"); |
| 197 | String persistentId = rs.getString("persistent_id"); |
| 198 | int depth = rs.getInt("depth"); |
| 199 | String namePath = rs.getString("name_path"); |
| 200 | policy = new SecurityRowMappers.PolicyRowMapper() |
| 201 | .mapRow(rs, 0); |
| 202 | |
| 203 | //todo: put active status here! |
| 204 | trace.put(pid, policy); |
| 205 | |
| 206 | //fixme: since leaves are mentioned first, maybe retrieve |
| 207 | SortedMap<String, KorAPResource.Container[]> submatch; |
| 208 | if ((submatch = containerMap.getPrefixSubMap(namePath)) |
| 209 | == null) { |
| 210 | |
| 211 | cursor = new KorAPResource.Container[depth + 1]; |
| 212 | cursor[depth] = new KorAPResource.Container( |
| 213 | persistentId, |
| 214 | ResourceFactory.getResource(rs.getInt("type")) |
| 215 | .getClass()); |
| 216 | containerMap.put(namePath, cursor); |
| 217 | }else { |
| 218 | KorAPResource.Container[] values = submatch |
| 219 | .get(submatch.firstKey()); |
| 220 | values[depth] = new KorAPResource.Container( |
| 221 | persistentId, |
| 222 | ResourceFactory.getResource(rs.getInt("type")) |
| 223 | .getClass()); |
| 224 | } |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | List<KorAPResource.Container> result = new ArrayList<>(); |
| 229 | for (KorAPResource.Container[] values : containerMap.values()) { |
| 230 | for (KorAPResource.Container container : values) |
| 231 | if (container == null) |
| 232 | containerMap.remove(values); |
| 233 | result.add(values[values.length - 1]); |
| 234 | } |
| 235 | return result; |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | } |