Skip to content

Commit 9aaa6d3

Browse files
authored
Merge pull request #55 from PatternAtlas/bugfix/initial_user_creation
Bugfix/initial user creation
2 parents cb13b7d + b30582d commit 9aaa6d3

File tree

6 files changed

+45
-11
lines changed

6 files changed

+45
-11
lines changed

.docker/application.properties.tpl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ spring.datasource.driver-class-name=org.postgresql.Driver
55
spring.datasource.url=jdbc:postgresql://{{.Env.JDBC_DATABASE_URL}}:{{.Env.JDBC_DATABASE_PORT}}/{{.Env.JDBC_DATABASE_NAME}}
66
spring.datasource.username={{.Env.JDBC_DATABASE_USERNAME}}
77
spring.datasource.password={{.Env.JDBC_DATABASE_PASSWORD}}
8-
spring.jpa.show-sql=true
8+
logging.level.io.github.patternatlas.api=info
9+
spring.jpa.show-sql=false
910
spring.jpa.generate-ddl=true
1011
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
1112
spring.jpa.hibernate.ddl-auto=update
1213
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
1314
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
14-
spring.jpa.properties.hibernate.show_sql=true
15+
spring.jpa.properties.hibernate.show_sql=false
1516
spring.jpa.properties.hibernate.format_sql=true
1617
spring.jpa.properties.hibernate.use_sql_comments=true
1718
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true

src/main/java/io/github/patternatlas/api/rest/controller/UserController.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.springframework.http.HttpStatus;
2929
import org.springframework.http.ResponseEntity;
3030
import org.springframework.security.access.prepost.PostFilter;
31+
import org.springframework.security.access.prepost.PreAuthorize;
3132
import org.springframework.security.crypto.password.PasswordEncoder;
3233
import org.springframework.web.bind.annotation.DeleteMapping;
3334
import org.springframework.web.bind.annotation.GetMapping;
@@ -93,6 +94,7 @@ ResponseEntity<EntityModel<UserModel>> getUserById(@PathVariable UUID userId) {
9394
*/
9495
@RequestMapping(method = RequestMethod.GET, value = "/userinfo")
9596
@ResponseBody
97+
@PreAuthorize(value = "isLoggedIn()") // must be checked here since user needs to be logged in to get info
9698
public Map<String, Object> user(Principal principal) {
9799
if (principal != null) {
98100
UUID id = UUID.fromString(principal.getName());

src/main/java/io/github/patternatlas/api/security/ResourceSecurityExpressionRoot.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.slf4j.Logger;
1818
import org.slf4j.LoggerFactory;
1919
import org.springframework.beans.factory.annotation.Autowired;
20+
import org.springframework.dao.DataIntegrityViolationException;
2021
import org.springframework.security.access.expression.SecurityExpressionRoot;
2122
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
2223
import org.springframework.security.core.Authentication;
@@ -52,6 +53,16 @@ public ResourceSecurityExpressionRoot(Authentication authentication,
5253
this.userAuthService = userAuthService;
5354
}
5455

56+
/**
57+
* Checks if the user is logged in and makes sure the token-Information
58+
* is stored in patternatlas db.
59+
* @return true if the user is present in db and logged in, false otherwise
60+
*/
61+
public boolean isLoggedIn() {
62+
Optional<UUID> userId = loggedInUUID();
63+
return userId.isPresent();
64+
}
65+
5566
/**
5667
* Checks global permission for user.
5768
* Will only check for the exact permission (e.g. ISSUE_CREATE)
@@ -83,13 +94,21 @@ private void createUser(UUID userId, Authentication authentication) {
8394
UserModelRequest req = new UserModelRequest();
8495
req.setId(userId);
8596
req.setName(preferredUsername);
86-
87-
if(this.userAuthService.hasUsers()) {
88-
// Create standard member user
89-
this.userAuthService.createInitialMember(req);
90-
} else {
91-
// There are no other users registered => create admin user as first user
92-
this.userAuthService.createInitialAdmin(req);
97+
try {
98+
if(this.userAuthService.hasUsers()) {
99+
// Create standard member user
100+
this.userAuthService.createInitialMember(req);
101+
} else {
102+
// There are no other users registered => create admin user as first user
103+
this.userAuthService.createInitialAdmin(req);
104+
}
105+
} catch (DataIntegrityViolationException e) {
106+
/*
107+
Is thrown if two simultaneous calls are the first calls a user makes to the API.
108+
In this case the second create user call will fail since both calls are made with
109+
the same ID. Since the call only fails if the user was properly created
110+
by the first call, this exception can be ignored.
111+
*/
93112
}
94113
} catch (JsonProcessingException e) {
95114
throw new UserNotFoundException("Cannot infer preferred username from Token");

src/main/java/io/github/patternatlas/api/service/UserAuthService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@
55

66
import java.util.UUID;
77

8+
import org.springframework.transaction.annotation.Isolation;
9+
import org.springframework.transaction.annotation.Transactional;
10+
811
/**
912
* Service for manipulating users based on incomping JW-Tokens.
1013
* Not to be used for REST-Access.
1114
* Used to query user information to handle authentication.
1215
*/
1316
public interface UserAuthService {
17+
18+
@Transactional
1419
UserEntity createInitialMember(UserModelRequest userModelRequest);
1520

21+
@Transactional
1622
UserEntity createInitialAdmin(UserModelRequest userModelRequest);
1723

1824
boolean userExists(UUID userId);

src/main/java/io/github/patternatlas/api/service/UserServiceImpl.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
import io.github.patternatlas.api.rest.model.user.RoleModelRequest;
1212
import io.github.patternatlas.api.rest.model.user.UserModelRequest;
1313

14+
import javax.validation.ConstraintViolationException;
1415
import org.slf4j.Logger;
1516
import org.slf4j.LoggerFactory;
17+
import org.springframework.dao.DataIntegrityViolationException;
1618
import org.springframework.data.rest.webmvc.ResourceNotFoundException;
1719
import org.springframework.security.crypto.password.PasswordEncoder;
1820
import org.springframework.stereotype.Service;
@@ -91,6 +93,7 @@ public UserEntity getUserById(UUID userId) {
9193
}
9294

9395
private UserEntity createInitialUser(UserModelRequest userModelRequest, String requestedRole) {
96+
logger.info("Automatically creating user " + userModelRequest.getName() + " (role: " + requestedRole + ")");
9497
UserEntity user = new UserEntity(userModelRequest, "");
9598
user.setEmail("");
9699
user.getRoles().add(this.roleRepository.findByName(requestedRole));
@@ -99,14 +102,14 @@ private UserEntity createInitialUser(UserModelRequest userModelRequest, String r
99102
}
100103

101104
@Override
105+
@Transactional
102106
public UserEntity createInitialMember(UserModelRequest userModelRequest) {
103107
return createInitialUser(userModelRequest, RoleConstant.MEMBER);
104108
}
105109

106110
@Override
111+
@Transactional
107112
public UserEntity createInitialAdmin(UserModelRequest userModelRequest) {
108-
logger.info("Automatically creating admin user " + userModelRequest.getName());
109-
110113
return createInitialUser(userModelRequest, RoleConstant.ADMIN);
111114
}
112115

src/main/resources/application.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ io.github.patternatlas.api.latexrenderer.port=5030
2424
server.servlet.contextPath=/patternatlas
2525
# liquibase file
2626
spring.liquibase.change-log=patternatlas.xml
27+
# DB debug logs
28+
spring.jpa.show-sql=false
29+
spring.jpa.properties.hibernate.show_sql=false

0 commit comments

Comments
 (0)