Port main's connect flow and OCR rotatePages onto the Quarkus branch

This commit is contained in:
Anthony Stirling
2026-09-02 10:19:24 +01:00
parent d959d49a1e
commit 4741e4f4a0
4 changed files with 28 additions and 14 deletions
@@ -63,6 +63,8 @@ public class AccountLinkController {
this.properties = properties;
}
public record LinkRequest(String supabaseJwt, String name) {}
/** {@code callbackUrl} is the portal telling us where its own callback route lives. */
public record ConnectStartRequest(String name, String callbackUrl) {}
@@ -12,20 +12,21 @@ import java.util.Base64;
import java.util.Locale;
import java.util.Optional;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import io.quarkus.arc.profile.IfBuildProfile;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;
import stirling.software.common.model.ApplicationProperties;
/** Browser-mediated account linking, instance side. */
// Arc cannot gate a bean on a runtime property, so the account-link flag no longer removes this
// bean; only the flag-gated endpoints reach it, so nothing links while the flag is off.
@Slf4j
@Service
@Profile("!saas")
@ConditionalOnProperty(name = "stirling.billing.account-link.enabled", havingValue = "true")
@ApplicationScoped
@IfBuildProfile("!saas")
public class ConnectService {
/** Frontend route that consumes the callback fragment. */
@@ -184,7 +185,7 @@ public class ConnectService {
};
}
@Transactional(readOnly = true)
@Transactional
public ConnectStatus status() {
Optional<DeviceCredential> credential = credentialStore.get();
if (credential.isPresent()) {
@@ -1,6 +1,21 @@
package stirling.software.proprietary.accountlink;
import org.springframework.data.jpa.repository.JpaRepository;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
/** Data access for the singleton {@link ConnectState} row. */
public interface ConnectStateRepository extends JpaRepository<ConnectState, Long> {}
@ApplicationScoped
public class ConnectStateRepository implements PanacheRepositoryBase<ConnectState, Long> {
/** Spring Data's {@code save}: the id is assigned, so a detached row has to merge. */
@Transactional
public ConnectState save(ConnectState state) {
if (state.getId() == null || getEntityManager().contains(state)) {
persist(state);
return state;
}
return getEntityManager().merge(state);
}
}
@@ -11,10 +11,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.redis.datasource.RedisDataSource;
import io.quarkus.redis.datasource.hash.HashCommands;
import io.quarkus.redis.datasource.keys.KeyCommands;