• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

square / keywhiz / 3625044908

pending completion
3625044908

Pull #1167

github

GitHub
Merge 67d37f551 into 62f0575ca
Pull Request #1167: Adding owner support to ClientDAO

55 of 55 new or added lines in 3 files covered. (100.0%)

5025 of 6504 relevant lines covered (77.26%)

0.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.06
/server/src/main/java/keywhiz/service/daos/GroupDAO.java
1
/*
2
 * Copyright (C) 2015 Square, Inc.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package keywhiz.service.daos;
18

19
import com.fasterxml.jackson.core.JsonProcessingException;
20
import com.fasterxml.jackson.databind.ObjectMapper;
21
import com.google.common.base.Throwables;
22
import com.google.common.collect.ImmutableMap;
23
import com.google.common.collect.ImmutableSet;
24
import java.time.OffsetDateTime;
25
import java.util.Optional;
26
import java.util.Set;
27
import java.util.stream.Collectors;
28
import javax.inject.Inject;
29
import keywhiz.api.model.Group;
30
import keywhiz.jooq.tables.Groups;
31
import keywhiz.jooq.tables.records.GroupsRecord;
32
import keywhiz.service.config.Readonly;
33
import org.jooq.Condition;
34
import org.jooq.Configuration;
35
import org.jooq.DSLContext;
36
import org.jooq.Record;
37
import org.jooq.Result;
38
import org.jooq.impl.DSL;
39

40
import static com.google.common.base.Preconditions.checkNotNull;
41
import static keywhiz.jooq.Tables.CLIENTS;
42
import static keywhiz.jooq.tables.Accessgrants.ACCESSGRANTS;
43
import static keywhiz.jooq.tables.Groups.GROUPS;
44
import static keywhiz.jooq.tables.Memberships.MEMBERSHIPS;
45
import static keywhiz.jooq.tables.Secrets.SECRETS;
46

47
public class GroupDAO {
48
  private static final Long NO_OWNER = null;
1✔
49

50
  private static final Groups GROUP_OWNERS = GROUPS.as("owners");
1✔
51

52
  private final DSLContext dslContext;
53
  private final GroupMapper groupMapper;
54
  private final ObjectMapper mapper;
55

56
  private GroupDAO(DSLContext dslContext, GroupMapper groupMapper, ObjectMapper mapper) {
1✔
57
    this.dslContext = dslContext;
1✔
58
    this.groupMapper = groupMapper;
1✔
59
    this.mapper = mapper;
1✔
60
  }
1✔
61

62
  public long createGroup(
63
      String name,
64
      String creator,
65
      String description,
66
      ImmutableMap<String, String> metadata) {
67
    return createGroup(
1✔
68
        name,
69
        creator,
70
        description,
71
        metadata,
72
        NO_OWNER);
73
  }
74

75
  public long createGroup(
76
      String name,
77
      String creator,
78
      String description,
79
      ImmutableMap<String, String> metadata,
80
      Long ownerId) {
81
    GroupsRecord r = dslContext.newRecord(GROUPS);
1✔
82

83
    String jsonMetadata;
84
    try {
85
      jsonMetadata = mapper.writeValueAsString(metadata);
1✔
86
    } catch (JsonProcessingException e) {
×
87
      // Serialization of a Map<String, String> can never fail.
88
      throw Throwables.propagate(e);
×
89
    }
1✔
90

91
    long now = OffsetDateTime.now().toEpochSecond();
1✔
92

93
    r.setName(name);
1✔
94
    r.setCreatedby(creator);
1✔
95
    r.setCreatedat(now);
1✔
96
    r.setUpdatedby(creator);
1✔
97
    r.setUpdatedat(now);
1✔
98
    r.setDescription(description);
1✔
99
    r.setMetadata(jsonMetadata);
1✔
100
    r.setOwner(ownerId);
1✔
101
    r.store();
1✔
102

103
    return r.getId();
1✔
104
  }
105

106
  public void deleteGroup(Group group) {
107
    dslContext.transaction(configuration -> {
1✔
108
      DSL.using(configuration)
1✔
109
              .delete(GROUPS)
1✔
110
              .where(GROUPS.ID.eq(group.getId()))
1✔
111
              .execute();
1✔
112
      DSL.using(configuration)
1✔
113
              .delete(MEMBERSHIPS)
1✔
114
              .where(MEMBERSHIPS.GROUPID.eq(group.getId()))
1✔
115
              .execute();
1✔
116
      DSL.using(configuration)
1✔
117
              .delete(ACCESSGRANTS)
1✔
118
              .where(ACCESSGRANTS.GROUPID.eq(group.getId()))
1✔
119
              .execute();
1✔
120
      DSL.using(configuration)
1✔
121
          .update(SECRETS)
1✔
122
          .set(SECRETS.OWNER, (Long) null)
1✔
123
          .where(SECRETS.OWNER.eq(group.getId()))
1✔
124
          .execute();
1✔
125
      DSL.using(configuration)
1✔
126
          .update(GROUPS)
1✔
127
          .set(GROUPS.OWNER, (Long) null)
1✔
128
          .where(GROUPS.OWNER.eq(group.getId()))
1✔
129
          .execute();
1✔
130
      DSL.using(configuration)
1✔
131
          .update(CLIENTS)
1✔
132
          .set(CLIENTS.OWNER, (Long) null)
1✔
133
          .where(CLIENTS.OWNER.eq(group.getId()))
1✔
134
          .execute();
1✔
135
    });
1✔
136
  }
1✔
137

138
  public Optional<Group> getGroup(String name) {
139
    return getGroup(GROUPS.NAME.eq(name));
1✔
140
  }
141

142
  public Optional<Group> getGroupById(long id) {
143
    return getGroup(GROUPS.ID.eq(id));
1✔
144
  }
145

146
  private Optional<Group> getGroup(Condition condition) {
147
    Record record = dslContext
1✔
148
        .select(GROUPS.fields())
1✔
149
        .select(GROUP_OWNERS.ID, GROUP_OWNERS.NAME)
1✔
150
        .from(GROUPS)
1✔
151
        .leftJoin(GROUP_OWNERS)
1✔
152
        .on(GROUPS.OWNER.eq(GROUP_OWNERS.ID))
1✔
153
        .where(condition)
1✔
154
        .fetchOne();
1✔
155

156
    return Optional.ofNullable(recordToGroup(record));
1✔
157
  }
158

159
  private Group recordToGroup(Record record) {
160
    if (record == null) {
1✔
161
      return null;
1✔
162
    }
163

164
    GroupsRecord groupRecord = record.into(GROUPS);
1✔
165
    GroupsRecord ownerRecord = record.into(GROUP_OWNERS);
1✔
166

167
    boolean danglingOwner = groupRecord.getOwner() != null && ownerRecord.getId() == null;
1✔
168
    if (danglingOwner) {
1✔
169
      throw new IllegalStateException(
×
170
          String.format(
×
171
              "Owner %s for group %s is missing.",
172
              groupRecord.getOwner(),
×
173
              groupRecord.getName()));
×
174
    }
175

176
    Group group = groupMapper.map(groupRecord);
1✔
177
    if (ownerRecord != null) {
1✔
178
      group.setOwner(ownerRecord.getName());
1✔
179
    }
180

181
    return group;
1✔
182
  }
183

184
  public ImmutableSet<Group> getGroups() {
185
    Result<Record> results = dslContext
1✔
186
        .select(GROUPS.fields())
1✔
187
        .select(GROUP_OWNERS.NAME)
1✔
188
        .from(GROUPS)
1✔
189
        .leftJoin(GROUP_OWNERS)
1✔
190
        .on(GROUPS.OWNER.eq(GROUP_OWNERS.ID))
1✔
191
        .fetch();
1✔
192

193
    Set<Group> groups = results.stream()
1✔
194
        .map(this::recordToGroup)
1✔
195
        .collect(Collectors.toSet());
1✔
196

197
    return ImmutableSet.copyOf(groups);
1✔
198
  }
199

200
  public static class GroupDAOFactory implements DAOFactory<GroupDAO> {
201
    private final DSLContext jooq;
202
    private final DSLContext readonlyJooq;
203
    private final GroupMapper groupMapper;
204
    private final ObjectMapper mapper;
205

206
    @Inject public GroupDAOFactory(DSLContext jooq, @Readonly DSLContext readonlyJooq,
207
        GroupMapper groupMapper, ObjectMapper mapper) {
1✔
208
      this.jooq = jooq;
1✔
209
      this.readonlyJooq = readonlyJooq;
1✔
210
      this.groupMapper = groupMapper;
1✔
211
      this.mapper = mapper;
1✔
212
    }
1✔
213

214
    @Override public GroupDAO readwrite() {
215
      return new GroupDAO(jooq, groupMapper, mapper);
1✔
216
    }
217

218
    @Override public GroupDAO readonly() {
219
      return new GroupDAO(readonlyJooq, groupMapper, mapper);
1✔
220
    }
221

222
    @Override public GroupDAO using(Configuration configuration) {
223
      DSLContext dslContext = DSL.using(checkNotNull(configuration));
1✔
224
      return new GroupDAO(dslContext, groupMapper, mapper);
1✔
225
    }
226

227
    public GroupDAO using(DSLContext dslContext) {
228
      return new GroupDAO(dslContext, groupMapper, mapper);
1✔
229
    }
230
  }
231
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc