Skip to content

Commit 8ee59b0

Browse files
authored
Merge pull request #4 from gridsuite/record_connections
record connections
2 parents c010d1c + c3329b7 commit 8ee59b0

File tree

9 files changed

+286
-17
lines changed

9 files changed

+286
-17
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import io.swagger.v3.oas.annotations.responses.ApiResponse;
1111
import io.swagger.v3.oas.annotations.responses.ApiResponses;
1212
import io.swagger.v3.oas.annotations.tags.Tag;
13+
import org.gridsuite.useradmin.server.repository.ConnectionEntity;
1314
import org.gridsuite.useradmin.server.repository.UserInfosEntity;
1415
import org.gridsuite.useradmin.server.service.UserAdminService;
1516
import org.springframework.http.MediaType;
@@ -65,4 +66,10 @@ public ResponseEntity<Void> userExists(@PathVariable("sub") String sub) {
6566
return service.subExists(sub) ? ResponseEntity.ok().build() : ResponseEntity.noContent().build();
6667
}
6768

69+
@GetMapping(value = "/connections")
70+
@Operation(summary = "get the connections")
71+
@ApiResponse(responseCode = "200", description = "The connections list")
72+
public ResponseEntity<List<ConnectionEntity>> getConnections(@RequestHeader("userId") String userId) {
73+
return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(service.getConnections(userId));
74+
}
6875
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 lombok.AllArgsConstructor;
10+
import lombok.Getter;
11+
import lombok.NoArgsConstructor;
12+
import lombok.Setter;
13+
14+
import javax.persistence.*;
15+
import java.time.LocalDateTime;
16+
import java.util.UUID;
17+
18+
/**
19+
* @author Etienne Homer <etienne.homer at rte-france.com>
20+
*/
21+
@NoArgsConstructor
22+
@AllArgsConstructor
23+
@Getter
24+
@Setter
25+
@Entity
26+
@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+
36+
@Column(name = "firstConnexionDate", nullable = false)
37+
private LocalDateTime firstConnexionDate;
38+
39+
@Column(name = "lastConnexionDate", nullable = false)
40+
private LocalDateTime lastConnexionDate;
41+
42+
@Column(name = "connectionAccepted", nullable = false)
43+
private Boolean connectionAccepted;
44+
45+
public ConnectionEntity(String sub, LocalDateTime firstConnexionDate, LocalDateTime lastConnexionDate, Boolean connectionAccepted) {
46+
this(UUID.randomUUID(), sub, firstConnexionDate, lastConnexionDate, connectionAccepted);
47+
}
48+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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 org.springframework.data.jpa.repository.JpaRepository;
10+
import org.springframework.stereotype.Repository;
11+
12+
import java.util.List;
13+
import java.util.UUID;
14+
15+
/**
16+
* @author Etienne Homer <etienne.homer at rte-france.com>
17+
*/
18+
@Repository
19+
public interface ConnectionRepository extends JpaRepository<ConnectionEntity, UUID> {
20+
List<ConnectionEntity> findBySub(String sub);
21+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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.service;
8+
9+
import org.gridsuite.useradmin.server.repository.ConnectionEntity;
10+
import org.gridsuite.useradmin.server.repository.ConnectionRepository;
11+
import org.springframework.stereotype.Service;
12+
import org.springframework.transaction.annotation.Transactional;
13+
14+
import java.time.LocalDateTime;
15+
import java.util.List;
16+
import java.util.Map;
17+
import java.util.Objects;
18+
import java.util.stream.Collectors;
19+
20+
/**
21+
* @author Etienne Homer <etienne.homer at rte-france.com>
22+
*/
23+
@Service
24+
public class ConnectionsService {
25+
26+
private ConnectionRepository connectionRepository;
27+
28+
public ConnectionsService(ConnectionRepository connectionRepository) {
29+
this.connectionRepository = Objects.requireNonNull(connectionRepository);
30+
}
31+
32+
@Transactional
33+
public void recordConnectionAttempt(String sub, Boolean isAllowed) {
34+
ConnectionEntity connectionEntity = connectionRepository.findBySub(sub).stream().findFirst().orElse(null);
35+
if (connectionEntity == null) {
36+
connectionEntity = new ConnectionEntity(sub, LocalDateTime.now(), LocalDateTime.now(), isAllowed);
37+
connectionRepository.save(connectionEntity);
38+
} else {
39+
connectionEntity.setLastConnexionDate(LocalDateTime.now());
40+
connectionEntity.setConnectionAccepted(isAllowed);
41+
}
42+
}
43+
44+
@Transactional
45+
public List<ConnectionEntity> removeDuplicates() {
46+
Map<String, List<ConnectionEntity>> connectionsBySub = connectionRepository.findAll().stream().collect(Collectors.groupingBy(ConnectionEntity::getSub));
47+
48+
connectionsBySub.keySet().forEach(sub ->
49+
connectionsBySub.get(sub).stream().skip(1).forEach(connectionEntity -> {
50+
ConnectionEntity groupedEntity = connectionsBySub.get(sub).get(0);
51+
if (connectionEntity.getLastConnexionDate().isAfter(groupedEntity.getLastConnexionDate())) {
52+
groupedEntity.setLastConnexionDate(connectionEntity.getLastConnexionDate());
53+
}
54+
if (connectionEntity.getFirstConnexionDate().isBefore(groupedEntity.getFirstConnexionDate())) {
55+
groupedEntity.setFirstConnexionDate(connectionEntity.getFirstConnexionDate());
56+
}
57+
connectionRepository.delete(connectionEntity);
58+
})
59+
);
60+
return connectionsBySub.values().stream().map(list -> list.get(0)).collect(Collectors.toList());
61+
}
62+
}

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

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88

99
import org.gridsuite.useradmin.server.UserAdminApplicationProps;
1010
import org.gridsuite.useradmin.server.UserAdminException;
11+
import org.gridsuite.useradmin.server.repository.ConnectionEntity;
1112
import org.gridsuite.useradmin.server.repository.UserAdminRepository;
1213
import org.gridsuite.useradmin.server.repository.UserInfosEntity;
1314
import org.springframework.beans.factory.annotation.Autowired;
1415
import org.springframework.stereotype.Service;
1516

16-
import java.util.List;
17-
import java.util.Objects;
18-
import java.util.UUID;
17+
import java.util.*;
1918

2019
import static org.gridsuite.useradmin.server.UserAdminException.Type.FORBIDDEN;
2120

@@ -24,39 +23,51 @@
2423
*/
2524
@Service
2625
public class UserAdminService {
27-
private UserAdminRepository repository;
26+
private UserAdminRepository userAdminRepository;
27+
28+
private ConnectionsService connectionsService;
2829

2930
@Autowired
3031
private UserAdminApplicationProps applicationProps;
3132

32-
public UserAdminService(UserAdminRepository repository) {
33-
this.repository = Objects.requireNonNull(repository);
33+
public UserAdminService(UserAdminRepository userAdminRepository, ConnectionsService connectionsService) {
34+
this.userAdminRepository = Objects.requireNonNull(userAdminRepository);
35+
this.connectionsService = Objects.requireNonNull(connectionsService);
3436
}
3537

3638
public List<UserInfosEntity> getUsers(String userId) {
3739
if (!isAdmin(userId)) {
3840
throw new UserAdminException(FORBIDDEN);
3941
}
40-
return repository.findAll();
42+
return userAdminRepository.findAll();
43+
}
44+
45+
public List<ConnectionEntity> getConnections(String userId) {
46+
if (!isAdmin(userId)) {
47+
throw new UserAdminException(FORBIDDEN);
48+
}
49+
return connectionsService.removeDuplicates();
4150
}
4251

4352
public void createUser(String sub, String userId) {
4453
if (!isAdmin(userId)) {
4554
throw new UserAdminException(FORBIDDEN);
4655
}
4756
UserInfosEntity userInfosEntity = new UserInfosEntity(sub);
48-
repository.save(userInfosEntity);
57+
userAdminRepository.save(userInfosEntity);
4958
}
5059

5160
public void delete(UUID id, String userId) {
5261
if (!isAdmin(userId)) {
5362
throw new UserAdminException(FORBIDDEN);
5463
}
55-
repository.deleteById(id);
64+
userAdminRepository.deleteById(id);
5665
}
5766

5867
public boolean subExists(String sub) {
59-
return (applicationProps.getAdmins().isEmpty() && repository.count() == 0) || !repository.findAllBySub(sub).isEmpty();
68+
Boolean isAllowed = (applicationProps.getAdmins().isEmpty() && userAdminRepository.count() == 0) || !userAdminRepository.findAllBySub(sub).isEmpty();
69+
connectionsService.recordConnectionAttempt(sub, isAllowed);
70+
return isAllowed.booleanValue();
6071
}
6172

6273
private boolean isAdmin(String sub) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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-4.1.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
3+
<changeSet author="homereti (generated)" id="1664524918797-1">
4+
<createTable tableName="connection">
5+
<column name="id" type="UUID">
6+
<constraints nullable="false" primaryKey="true" primaryKeyName="connectionPK"/>
7+
</column>
8+
<column name="connection_accepted" type="BOOLEAN">
9+
<constraints nullable="false"/>
10+
</column>
11+
<column name="first_connexion_date" type="TIMESTAMP">
12+
<constraints nullable="false"/>
13+
</column>
14+
<column name="last_connexion_date" type="TIMESTAMP">
15+
<constraints nullable="false"/>
16+
</column>
17+
<column name="sub" type="VARCHAR(255)">
18+
<constraints nullable="false"/>
19+
</column>
20+
</createTable>
21+
</changeSet>
22+
<changeSet author="homereti (generated)" id="1664524918797-2">
23+
<createIndex indexName="connection_sub_index" tableName="connection">
24+
<column name="sub"/>
25+
</createIndex>
26+
</changeSet>
27+
</databaseChangeLog>

src/main/resources/db/changelog/db.changelog-master.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ databaseChangeLog:
33
- include:
44
file: changesets/changelog_2022-09-21T09:10:49Z.xml
55
relativeToChangelogFile: true
6+
7+
- include:
8+
file: changesets/changelog_2022-09-30T08:01:49Z.xml
9+
relativeToChangelogFile: true

src/test/java/org/gridsuite/useradmin/server/NoAdminTest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package org.gridsuite.useradmin.server;
88

99
import com.fasterxml.jackson.databind.ObjectMapper;
10+
import org.gridsuite.useradmin.server.repository.ConnectionRepository;
1011
import org.gridsuite.useradmin.server.repository.UserAdminRepository;
1112
import org.gridsuite.useradmin.server.repository.UserInfosEntity;
1213
import org.junit.Before;
@@ -40,10 +41,14 @@ public class NoAdminTest {
4041
ObjectMapper objectMapper = new ObjectMapper();
4142

4243
@Autowired
43-
private UserAdminRepository repository;
44+
private UserAdminRepository userAdminRepository;
45+
46+
@Autowired
47+
private ConnectionRepository connectionRepository;
4448

4549
private void cleanDB() {
46-
repository.deleteAll();
50+
userAdminRepository.deleteAll();
51+
connectionRepository.deleteAll();
4752
}
4853

4954
@Before
@@ -58,7 +63,7 @@ public void testNoAdmin() throws Exception {
5863
.andReturn();
5964

6065
UserInfosEntity userInfosEntity = new UserInfosEntity("newUser");
61-
repository.save(userInfosEntity);
66+
userAdminRepository.save(userInfosEntity);
6267

6368
mockMvc.perform(head("/" + UserAdminApi.API_VERSION + "/users/{sub}", "NOT_REGISTERED_USER"))
6469
.andExpect(status().isNoContent())

0 commit comments

Comments
 (0)