Skip to content

Commit ebfa248

Browse files
Fix duplicate entries in records
1 parent c7a55fb commit ebfa248

File tree

11 files changed

+138
-46
lines changed

11 files changed

+138
-46
lines changed

src/main/java/org/gridsuite/useradmin/server/UserAdminController.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,12 @@ public ResponseEntity<Void> userExists(@PathVariable("sub") String sub) {
7272
public ResponseEntity<List<ConnectionEntity>> getConnections(@RequestHeader("userId") String userId) {
7373
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(service.getConnections(userId));
7474
}
75+
76+
@Deprecated(forRemoval = true)
77+
@GetMapping(value = "/connections/deduplicate")
78+
@Operation(summary = "get the connections deduplicated", deprecated = true)
79+
@ApiResponse(responseCode = "200", description = "The connections list")
80+
public ResponseEntity<List<ConnectionEntity>> deduplicateConnections(@RequestHeader("userId") String userId) {
81+
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(service.getDeduplicatedConnections(userId));
82+
}
7583
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright (c) 2022, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.useradmin.server.repository;
8+
9+
import jakarta.persistence.*;
10+
import lombok.AllArgsConstructor;
11+
import lombok.Getter;
12+
import lombok.NoArgsConstructor;
13+
import lombok.Setter;
14+
15+
import java.util.UUID;
16+
17+
/**
18+
* @author Etienne Homer <etienne.homer at rte-france.com>
19+
*/
20+
@NoArgsConstructor
21+
@AllArgsConstructor
22+
@Getter
23+
@Setter
24+
@MappedSuperclass
25+
abstract class AbstractUserEntity {
26+
public AbstractUserEntity(String sub) {
27+
this(UUID.randomUUID(), sub);
28+
}
29+
30+
@Id
31+
@GeneratedValue(strategy = GenerationType.AUTO)
32+
@Column(name = "id")
33+
private UUID id;
34+
35+
@Column(name = "sub", nullable = false, unique = true)
36+
private String sub;
37+
}

src/main/java/org/gridsuite/useradmin/server/repository/ConnectionEntity.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
*/
77
package org.gridsuite.useradmin.server.repository;
88

9+
import jakarta.persistence.Column;
10+
import jakarta.persistence.Entity;
11+
import jakarta.persistence.Index;
12+
import jakarta.persistence.Table;
913
import lombok.AllArgsConstructor;
1014
import lombok.Getter;
1115
import lombok.NoArgsConstructor;
1216
import lombok.Setter;
1317

14-
import jakarta.persistence.*;
1518
import java.time.LocalDateTime;
16-
import java.util.UUID;
1719

1820
/**
1921
* @author Etienne Homer <etienne.homer at rte-france.com>
@@ -24,15 +26,7 @@
2426
@Setter
2527
@Entity
2628
@Table(name = "connection", indexes = {@Index(name = "connection_sub_index", columnList = "sub")})
27-
public class ConnectionEntity {
28-
29-
@Id
30-
@Column(name = "id")
31-
private UUID id;
32-
33-
@Column(name = "sub", nullable = false)
34-
private String sub;
35-
29+
public class ConnectionEntity extends AbstractUserEntity {
3630
@Column(name = "firstConnexionDate", nullable = false)
3731
private LocalDateTime firstConnexionDate;
3832

@@ -43,6 +37,9 @@ public class ConnectionEntity {
4337
private Boolean connectionAccepted;
4438

4539
public ConnectionEntity(String sub, LocalDateTime firstConnexionDate, LocalDateTime lastConnexionDate, Boolean connectionAccepted) {
46-
this(UUID.randomUUID(), sub, firstConnexionDate, lastConnexionDate, connectionAccepted);
40+
super(sub);
41+
this.firstConnexionDate = firstConnexionDate;
42+
this.lastConnexionDate = lastConnexionDate;
43+
this.connectionAccepted = connectionAccepted;
4744
}
4845
}

src/main/java/org/gridsuite/useradmin/server/repository/ConnectionRepository.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,30 @@
66
*/
77
package org.gridsuite.useradmin.server.repository;
88

9+
import jakarta.transaction.Transactional;
910
import org.springframework.data.jpa.repository.JpaRepository;
11+
import org.springframework.data.jpa.repository.Modifying;
12+
import org.springframework.lang.NonNull;
1013
import org.springframework.stereotype.Repository;
1114

12-
import java.util.List;
15+
import java.time.LocalDateTime;
16+
import java.util.Optional;
1317
import java.util.UUID;
1418

1519
/**
1620
* @author Etienne Homer <etienne.homer at rte-france.com>
1721
*/
1822
@Repository
1923
public interface ConnectionRepository extends JpaRepository<ConnectionEntity, UUID> {
20-
List<ConnectionEntity> findBySub(String sub);
24+
@NonNull
25+
Optional<ConnectionEntity> findBySub/*IgnoreCase*/(@NonNull String sub);
26+
27+
@Transactional()
28+
@Modifying
29+
default void recordNewConnection(@NonNull final String sub, final boolean connectionAccepted) {
30+
this.findBySub/*IgnoreCase*/(sub).ifPresentOrElse(
31+
conn -> this.save(conn.setLastConnexionDate(LocalDateTime.now()).setConnectionAccepted(connectionAccepted)),
32+
() -> this.save(new ConnectionEntity(sub, LocalDateTime.now(), LocalDateTime.now(), connectionAccepted))
33+
);
34+
}
2135
}

src/main/java/org/gridsuite/useradmin/server/repository/UserInfosEntity.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,24 @@
66
*/
77
package org.gridsuite.useradmin.server.repository;
88

9-
import lombok.AllArgsConstructor;
9+
import jakarta.persistence.Entity;
10+
import jakarta.persistence.Index;
11+
import jakarta.persistence.Table;
1012
import lombok.Getter;
1113
import lombok.NoArgsConstructor;
1214
import lombok.Setter;
1315

14-
import jakarta.persistence.*;
15-
import java.util.UUID;
16-
1716
/**
1817
* @author Etienne Homer <etienne.homer at rte-france.com>
1918
*/
2019
@NoArgsConstructor
21-
@AllArgsConstructor
20+
//@AllArgsConstructor
2221
@Getter
2322
@Setter
2423
@Entity
2524
@Table(name = "user_infos", indexes = {@Index(name = "user_infos_sub_index", columnList = "sub")})
26-
public class UserInfosEntity {
27-
25+
public class UserInfosEntity extends AbstractUserEntity {
2826
public UserInfosEntity(String sub) {
29-
this(UUID.randomUUID(), sub);
27+
super(sub);
3028
}
31-
32-
@Id
33-
@Column(name = "id")
34-
private UUID id;
35-
36-
@Column(name = "sub", nullable = false)
37-
private String sub;
3829
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lombok.accessors.chain = true

src/main/java/org/gridsuite/useradmin/server/service/ConnectionsService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public void recordConnectionAttempt(String sub, Boolean isAllowed) {
4343
}
4444
}
4545

46+
@Deprecated(forRemoval = true)
4647
@Transactional
4748
public List<ConnectionEntity> removeDuplicates() {
4849
Map<String, List<ConnectionEntity>> connectionsBySub = connectionRepository.findAll().stream().collect(Collectors.groupingBy(ConnectionEntity::getSub));

src/main/java/org/gridsuite/useradmin/server/service/UserAdminService.java

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,34 @@
66
*/
77
package org.gridsuite.useradmin.server.service;
88

9+
import lombok.RequiredArgsConstructor;
910
import org.gridsuite.useradmin.server.UserAdminApplicationProps;
1011
import org.gridsuite.useradmin.server.UserAdminException;
1112
import org.gridsuite.useradmin.server.repository.ConnectionEntity;
13+
import org.gridsuite.useradmin.server.repository.ConnectionRepository;
1214
import org.gridsuite.useradmin.server.repository.UserAdminRepository;
1315
import org.gridsuite.useradmin.server.repository.UserInfosEntity;
1416
import org.springframework.beans.factory.annotation.Autowired;
1517
import org.springframework.stereotype.Service;
1618

17-
import java.util.*;
19+
import java.util.List;
20+
import java.util.UUID;
1821

1922
import static org.gridsuite.useradmin.server.UserAdminException.Type.FORBIDDEN;
2023

2124
/**
2225
* @author Etienne Homer <etienne.homer at rte-france.com>
2326
*/
27+
@RequiredArgsConstructor
2428
@Service
2529
public class UserAdminService {
26-
private UserAdminRepository userAdminRepository;
27-
28-
private ConnectionsService connectionsService;
30+
private final UserAdminRepository userAdminRepository;
31+
private final ConnectionRepository connectionRepository;
32+
private final ConnectionsService connectionsService;
2933

3034
@Autowired
3135
private UserAdminApplicationProps applicationProps;
3236

33-
public UserAdminService(UserAdminRepository userAdminRepository, ConnectionsService connectionsService) {
34-
this.userAdminRepository = Objects.requireNonNull(userAdminRepository);
35-
this.connectionsService = Objects.requireNonNull(connectionsService);
36-
}
37-
3837
public List<UserInfosEntity> getUsers(String userId) {
3938
if (!isAdmin(userId)) {
4039
throw new UserAdminException(FORBIDDEN);
@@ -43,6 +42,14 @@ public List<UserInfosEntity> getUsers(String userId) {
4342
}
4443

4544
public List<ConnectionEntity> getConnections(String userId) {
45+
if (!isAdmin(userId)) {
46+
throw new UserAdminException(FORBIDDEN);
47+
}
48+
return connectionRepository.findAll();
49+
}
50+
51+
@Deprecated(forRemoval = true)
52+
public List<ConnectionEntity> getDeduplicatedConnections(String userId) {
4653
if (!isAdmin(userId)) {
4754
throw new UserAdminException(FORBIDDEN);
4855
}
@@ -65,7 +72,9 @@ public void delete(UUID id, String userId) {
6572
}
6673

6774
public boolean subExists(String sub) {
68-
Boolean isAllowed = applicationProps.getAdmins().isEmpty() && userAdminRepository.count() == 0 || applicationProps.getAdmins().contains(sub) || !userAdminRepository.findAllBySub(sub).isEmpty();
75+
Boolean isAllowed = applicationProps.getAdmins().isEmpty() && userAdminRepository.count() == 0
76+
|| applicationProps.getAdmins().contains(sub)
77+
|| !userAdminRepository.findAllBySub(sub).isEmpty();
6978
connectionsService.recordConnectionAttempt(sub, isAllowed);
7079
return isAllowed.booleanValue();
7180
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
2+
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
3+
<changeSet author="chuinetri" id="1704818243021-0">
4+
<comment>Deduplicate rows before adding unique constraint</comment>
5+
<delete tableName="user_infos">
6+
<where>id in (select id from (select row_number() over (partition by sub) as rnb, * from user_infos) subquery where rnb > 1)</where>
7+
</delete>
8+
9+
<sql stripComments="true" dbms="!oracle">
10+
update connection c1 set
11+
first_connexion_date = (select min(c2.first_connexion_date) from connection c2 where c2.sub=c1.sub group by c2.sub),
12+
last_connexion_date = (select max(c2.last_connexion_date) from connection c2 where c2.sub=c1.sub group by c2.sub),
13+
connection_accepted = (select connection_accepted from connection c2 where (c2.sub, c2.last_connexion_date) in (
14+
select c3.sub, max(c3.last_connexion_date) from connection c3 where c3.sub=c1.sub group by c3.sub) limit 1);
15+
</sql>
16+
<sql stripComments="true" dbms="oracle">
17+
--oracle use fetch instead of limit
18+
update connection c1 set
19+
first_connexion_date = (select min(c2.first_connexion_date) from connection c2 where c2.sub=c1.sub group by c2.sub),
20+
last_connexion_date = (select max(c2.last_connexion_date) from connection c2 where c2.sub=c1.sub group by c2.sub),
21+
connection_accepted = (select connection_accepted from connection c2 where (c2.sub, c2.last_connexion_date) in (
22+
select c3.sub, max(c3.last_connexion_date) from connection c3 where c3.sub=c1.sub group by c3.sub) FETCH FIRST 1 ROW ONLY);
23+
</sql>
24+
<delete tableName="connection">
25+
<where>id in (select id from (select row_number() over (partition by sub) as rnb, * from connection) subquery where rnb > 1)</where>
26+
</delete>
27+
</changeSet>
28+
29+
<changeSet author="chuinetri" id="1704818243021-1">
30+
<addUniqueConstraint columnNames="sub" constraintName="UC_USER_INFOSSUB_COL" tableName="user_infos"/>
31+
<addUniqueConstraint columnNames="sub" constraintName="UC_CONNECTIONSUB_COL" tableName="connection"/>
32+
</changeSet>
33+
</databaseChangeLog>
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
databaseChangeLog:
2-
32
- include:
43
file: changesets/changelog_20220921T091049Z.xml
54
relativeToChangelogFile: true
6-
75
- include:
86
file: changesets/changelog_20220930T080149Z.xml
97
relativeToChangelogFile: true
8+
- include:
9+
file: changesets/changelog_20240109T161028Z.xml
10+
relativeToChangelogFile: true

0 commit comments

Comments
 (0)