feat(android): add device activation flow and update dependencies
重构项目架构,引入启动页(SplashActivity)检查激活状态,未激活设备引导至激活页(ActivationActivity)完成provision+token流程。集成Retrofit+RxJava3网络层、Room数据库、Lifecycle组件、MMKV等依赖,升级OkHttp/Gson版本,并将构建配置从旧项目全面迁移至新项目结构。
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package com.ttstd.signaling.store;
|
||||
|
||||
import com.ttstd.signaling.model.AdminAccount;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 后台管理员存储抽象。与 {@code UserStore} 互不耦合,JPA 与内存两套实现可切换。
|
||||
*/
|
||||
public interface AdminStore {
|
||||
|
||||
AdminAccount save(AdminAccount admin);
|
||||
|
||||
Optional<AdminAccount> findById(String adminId);
|
||||
|
||||
Optional<AdminAccount> findByUsername(String username);
|
||||
|
||||
boolean existsByUsername(String username);
|
||||
|
||||
boolean existsById(String adminId);
|
||||
|
||||
List<AdminAccount> findAll();
|
||||
|
||||
long count();
|
||||
|
||||
void delete(String adminId);
|
||||
}
|
||||
@@ -16,7 +16,13 @@ public interface DeviceStore {
|
||||
DeviceAccount save(DeviceAccount account);
|
||||
List<DeviceAccount> listAll();
|
||||
|
||||
/** 删除设备。设备不存在时静默返回。 */
|
||||
void delete(String deviceUid);
|
||||
|
||||
boolean isSnAllowed(String sn);
|
||||
void addAllowedSn(DeviceAllowlist entry);
|
||||
List<DeviceAllowlist> listAllowed();
|
||||
|
||||
/** 从 SN 白名单移除条目。 */
|
||||
void removeAllowedSn(String sn);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ttstd.signaling.store;
|
||||
|
||||
import com.ttstd.signaling.model.AdminAccount;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/** 内存实现:不依赖数据库,用于测试与本地演示(storage.mode=memory)。 */
|
||||
@Component
|
||||
@Profile("memory")
|
||||
public class InMemoryAdminStore implements AdminStore {
|
||||
|
||||
private final ConcurrentMap<String, AdminAccount> byId = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<String, String> usernameToId = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public synchronized AdminAccount save(AdminAccount admin) {
|
||||
byId.put(admin.getAdminId(), admin);
|
||||
if (admin.getUsername() != null) {
|
||||
usernameToId.put(admin.getUsername().toLowerCase(java.util.Locale.ROOT), admin.getAdminId());
|
||||
}
|
||||
return admin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AdminAccount> findById(String adminId) {
|
||||
return Optional.ofNullable(byId.get(adminId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AdminAccount> findByUsername(String username) {
|
||||
if (username == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
String id = usernameToId.get(username.toLowerCase(java.util.Locale.ROOT));
|
||||
return Optional.ofNullable(id == null ? null : byId.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByUsername(String username) {
|
||||
if (username == null) {
|
||||
return false;
|
||||
}
|
||||
return usernameToId.containsKey(username.toLowerCase(java.util.Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsById(String adminId) {
|
||||
return byId.containsKey(adminId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AdminAccount> findAll() {
|
||||
return List.copyOf(byId.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return byId.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void delete(String adminId) {
|
||||
AdminAccount removed = byId.remove(adminId);
|
||||
if (removed != null && removed.getUsername() != null) {
|
||||
usernameToId.remove(removed.getUsername().toLowerCase(java.util.Locale.ROOT));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,6 +48,14 @@ public class InMemoryDeviceStore implements DeviceStore {
|
||||
return List.copyOf(byUid.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void delete(String deviceUid) {
|
||||
DeviceAccount removed = byUid.remove(deviceUid);
|
||||
if (removed != null) {
|
||||
snToUid.remove(removed.getSn());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isSnAllowed(String sn) {
|
||||
return allowlist.containsKey(sn);
|
||||
@@ -62,4 +70,9 @@ public class InMemoryDeviceStore implements DeviceStore {
|
||||
public synchronized List<DeviceAllowlist> listAllowed() {
|
||||
return List.copyOf(allowlist.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void removeAllowedSn(String sn) {
|
||||
allowlist.remove(sn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,4 +45,12 @@ public class InMemoryUserStore implements UserStore {
|
||||
public synchronized List<UserAccount> listAll() {
|
||||
return List.copyOf(byId.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void delete(String userId) {
|
||||
UserAccount removed = byId.remove(userId);
|
||||
if (removed != null) {
|
||||
usernameToId.remove(removed.getUsername());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.ttstd.signaling.store;
|
||||
|
||||
import com.ttstd.signaling.model.AdminAccount;
|
||||
import com.ttstd.signaling.repository.AdminAccountRepository;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/** JPA 实现:管理员账号持久化到 MySQL。仅在 storage.mode=jpa(默认)时生效。 */
|
||||
@Component
|
||||
@Profile("!memory")
|
||||
public class JpaAdminStore implements AdminStore {
|
||||
|
||||
private final AdminAccountRepository repository;
|
||||
|
||||
public JpaAdminStore(AdminAccountRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdminAccount save(AdminAccount admin) {
|
||||
return repository.save(admin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AdminAccount> findById(String adminId) {
|
||||
return repository.findById(adminId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AdminAccount> findByUsername(String username) {
|
||||
return repository.findByUsername(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsByUsername(String username) {
|
||||
return repository.existsByUsername(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsById(String adminId) {
|
||||
return repository.existsById(adminId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AdminAccount> findAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
return repository.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String adminId) {
|
||||
repository.deleteById(adminId);
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,11 @@ public class JpaDeviceStore implements DeviceStore {
|
||||
return deviceRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String deviceUid) {
|
||||
deviceRepository.deleteById(deviceUid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSnAllowed(String sn) {
|
||||
return allowlistRepository.existsBySn(sn);
|
||||
@@ -63,4 +68,9 @@ public class JpaDeviceStore implements DeviceStore {
|
||||
public List<DeviceAllowlist> listAllowed() {
|
||||
return allowlistRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAllowedSn(String sn) {
|
||||
allowlistRepository.deleteById(sn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,4 +43,9 @@ public class JpaUserStore implements UserStore {
|
||||
public List<UserAccount> listAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String userId) {
|
||||
repository.deleteById(userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,7 @@ public interface UserStore {
|
||||
boolean existsByUsername(String username);
|
||||
UserAccount save(UserAccount account);
|
||||
List<UserAccount> listAll();
|
||||
|
||||
/** 删除账号。账号不存在时静默返回。 */
|
||||
void delete(String userId);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user