9
9
import io .hyperfoil .tools .horreum .svc .Roles ;
10
10
import io .hyperfoil .tools .horreum .svc .user .UserBackEnd ;
11
11
import io .quarkus .logging .Log ;
12
+ import io .quarkus .runtime .LaunchMode ;
12
13
import io .quarkus .runtime .StartupEvent ;
13
14
import jakarta .enterprise .context .ApplicationScoped ;
14
15
import jakarta .enterprise .event .Observes ;
25
26
import java .util .Map ;
26
27
import java .util .Optional ;
27
28
28
- import static io .quarkus .runtime .configuration .ProfileManager .getLaunchMode ;
29
-
30
29
@ ApplicationScoped public class SecurityBootstrap {
31
30
32
31
@ ConfigProperty (name = "quarkus.keycloak.admin-client.server-url" ) Optional <String > keycloakURL ;
39
38
private static final String MIGRATION_PROVIDER = "database" ;
40
39
private static final String BOOTSTRAP_ACCOUNT = "horreum.bootstrap" ;
41
40
42
- private static final char [] RANDOM_PASSWRORD_CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ).toCharArray ();
41
+ private static final char [] RANDOM_PASSWORD_CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ).toCharArray ();
43
42
private static final int RANDOM_PASSWORD_DEFAULT_LENGTH = 16 ;
44
43
45
44
@ Inject RoleManager roleManager ;
@@ -115,15 +114,16 @@ private void addTeamMembership(UserInfo userInfo, String teamName, TeamRole role
115
114
* Create an admin account if there are no accounts in the system.
116
115
* The account should be removed once other accounts are created.
117
116
*/
118
- public void checkBootstrapAccount () {
117
+ @ WithRoles (extras = BOOTSTRAP_ACCOUNT )
118
+ @ Transactional public void checkBootstrapAccount () {
119
119
// checks the list of administrators. a user cannot remove himself nor create the bootstrap account (restricted namespace)
120
120
List <String > administrators = backend .get ().administrators ().stream ().map (userData -> userData .username ).toList ();
121
121
if (administrators .isEmpty ()) {
122
122
UserService .NewUser user = new UserService .NewUser ();
123
- user .
user =
new UserService .
UserData (
"" ,
BOOTSTRAP_ACCOUNT ,
"Bootstrap" ,
"Acount " ,
"[email protected] " );
124
- user .password = providedBootstrapPassword .orElseGet (() -> getLaunchMode ().isDevOrTest () ? "secret" : generateRandomPassword (RANDOM_PASSWORD_DEFAULT_LENGTH ));
123
+ user .
user =
new UserService .
UserData (
"" ,
BOOTSTRAP_ACCOUNT ,
"Bootstrap" ,
"Account " ,
"[email protected] " );
124
+ user .password = providedBootstrapPassword .orElseGet (() -> LaunchMode . current ().isDevOrTest () ? "secret" : generateRandomPassword (RANDOM_PASSWORD_DEFAULT_LENGTH ));
125
125
126
- // create bootstrap acconut with admin role
126
+ // create bootstrap account with admin role
127
127
backend .get ().createUser (user );
128
128
backend .get ().setPassword (BOOTSTRAP_ACCOUNT , user .password ); // KeycloakUserBackend.createUser() creates a temp password, with this call the password is usable
129
129
backend .get ().updateAdministrators (List .of (BOOTSTRAP_ACCOUNT ));
@@ -132,6 +132,10 @@ public void checkBootstrapAccount() {
132
132
backend .get ().addTeam ("dev-team" );
133
133
backend .get ().updateTeamMembers ("dev-team" , Map .of (BOOTSTRAP_ACCOUNT , List .of (Roles .MANAGER , Roles .TESTER , Roles .UPLOADER , Roles .VIEWER )));
134
134
135
+ // create db entry, if not existent, like in UserService.createLocalUser()
136
+ UserInfo userInfo = UserInfo .<UserInfo >findByIdOptional (BOOTSTRAP_ACCOUNT ).orElse (new UserInfo (BOOTSTRAP_ACCOUNT ));
137
+ userInfo .defaultTeam = "dev-team" ;
138
+
135
139
Log .infov ("\n >>>\n >>> Created temporary account {0} with password {1}\n >>>" , BOOTSTRAP_ACCOUNT , user .password );
136
140
} else if (administrators .size () > 1 && administrators .contains (BOOTSTRAP_ACCOUNT )) {
137
141
Log .warnv ("The temporary account {0} can be removed" , BOOTSTRAP_ACCOUNT );
@@ -140,7 +144,7 @@ public void checkBootstrapAccount() {
140
144
141
145
public static String generateRandomPassword (int lenght ) {
142
146
StringBuilder builder = new StringBuilder (lenght );
143
- new SecureRandom ().ints (lenght , 0 , RANDOM_PASSWRORD_CHARS .length ).mapToObj (i -> RANDOM_PASSWRORD_CHARS [i ]).forEach (builder ::append );
147
+ new SecureRandom ().ints (lenght , 0 , RANDOM_PASSWORD_CHARS .length ).mapToObj (i -> RANDOM_PASSWORD_CHARS [i ]).forEach (builder ::append );
144
148
return builder .toString ();
145
149
}
146
150
0 commit comments