fix(tenants): keep the 'system' username when provisioning a new tenant
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Problem
Commit 3d3ce92e9 personalised the three users seeded into a brand-new
tenant database and renamed user id 2 from 'system' to
'<tenant>_system' (for example 'default_system'). Fineract looks this
user up by the fixed name AppUserConstants.SYSTEM_USER_NAME ('system')
through AppUserRepositoryWrapper.fetchSystemUser(), so on every fresh
tenant:
- every scheduler job failed once a minute with
"UserNotFoundException: User with name 'system' does not exist"
(seen with the Send Asynchronous Events job);
- COB initialisation, savings escheat, current account closure and the
stuck-job listener would fail in the same way.
Existing tenants were not affected because the provisioner only runs
right after the very first migration of a new tenant.
Fix
- TenantInitialUserProvisioner now sets user id 2's username to
AppUserConstants.SYSTEM_USER_NAME and only replaces its password.
- Admin and interop users are still personalised as
'<tenant>_admin' and '<tenant>_interop'.
- Javadoc and the startup log line now say the system user keeps its
name and why.
Resulting users on a new tenant
- <tenant>_admin (password: initial-user-password or built-in default)
- system (same password, name unchanged)
- <tenant>_interop (same password)
Tenants already created with '<tenant>_system' need a one-off fix:
UPDATE m_appuser SET username = 'system' WHERE id = 2;
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+7
-5
@@ -22,6 +22,7 @@ import java.util.Locale;
|
|||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.useradministration.service.AppUserConstants;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||||
@@ -37,8 +38,9 @@ import org.springframework.stereotype.Component;
|
|||||||
* touched. The seeded changeSet itself is deliberately left alone: editing it would change its Liquibase checksum and
|
* touched. The seeded changeSet itself is deliberately left alone: editing it would change its Liquibase checksum and
|
||||||
* break validation on every tenant that already ran it.
|
* break validation on every tenant that already ran it.
|
||||||
*
|
*
|
||||||
* Usernames become {@code <tenantIdentifier>_admin}, {@code <tenantIdentifier>_system} and
|
* Usernames become {@code <tenantIdentifier>_admin} and {@code <tenantIdentifier>_interop}. The system user keeps the
|
||||||
* {@code <tenantIdentifier>_interop}. All three share one password: the value of
|
* {@link AppUserConstants#SYSTEM_USER_NAME} username because scheduler jobs, COB and other background processes look it
|
||||||
|
* up by that name; only its password is changed. All three share one password: the value of
|
||||||
* {@code fineract.tenant.initial-user-password} (env {@code FINERACT_TENANT_INITIAL_USER_PASSWORD}) when set,
|
* {@code fineract.tenant.initial-user-password} (env {@code FINERACT_TENANT_INITIAL_USER_PASSWORD}) when set,
|
||||||
* otherwise {@link #DEFAULT_PASSWORD}.
|
* otherwise {@link #DEFAULT_PASSWORD}.
|
||||||
*/
|
*/
|
||||||
@@ -68,11 +70,11 @@ public class TenantInitialUserProvisioner {
|
|||||||
final String encoded = encoder.encode(password);
|
final String encoded = encoder.encode(password);
|
||||||
|
|
||||||
update(jdbc, ADMIN_ID, prefix + "_admin", encoded);
|
update(jdbc, ADMIN_ID, prefix + "_admin", encoded);
|
||||||
update(jdbc, SYSTEM_ID, prefix + "_system", encoded);
|
update(jdbc, SYSTEM_ID, AppUserConstants.SYSTEM_USER_NAME, encoded);
|
||||||
update(jdbc, INTEROP_ID, prefix + "_interop", encoded);
|
update(jdbc, INTEROP_ID, prefix + "_interop", encoded);
|
||||||
|
|
||||||
log.warn("Tenant '{}' initial users created: {}_admin, {}_system, {}_interop (password: {}). Change it after first login.",
|
log.warn("Tenant '{}' initial users created: {}_admin, {}, {}_interop (password: {}). Change it after first login.",
|
||||||
tenantIdentifier, prefix, prefix, prefix, overridden ? "from " + PASSWORD_PROPERTY : "built-in default");
|
tenantIdentifier, prefix, AppUserConstants.SYSTEM_USER_NAME, prefix, overridden ? "from " + PASSWORD_PROPERTY : "built-in default");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update(final JdbcTemplate jdbc, final long id, final String username, final String encodedPassword) {
|
private void update(final JdbcTemplate jdbc, final long id, final String username, final String encodedPassword) {
|
||||||
|
|||||||
Reference in New Issue
Block a user