152 lines
4.5 KiB
Swift
152 lines
4.5 KiB
Swift
//
|
|
// LoginState.swift
|
|
// punchnet
|
|
//
|
|
// Created by 安礼成 on 2026/1/16.
|
|
//
|
|
|
|
import Foundation
|
|
import Observation
|
|
|
|
struct AppContextError: Error {
|
|
let message: String
|
|
}
|
|
|
|
@Observable
|
|
class AppContext {
|
|
private var vpnManager = VPNManager.shared
|
|
|
|
var noticePort: Int
|
|
|
|
// 调用 "/connect" 之后的网络信息
|
|
var networkContext: SDLAPIClient.NetworkContext = .default()
|
|
|
|
// 保存当前登陆vpn使用的配置项
|
|
var vpnOptions: [String: NSObject]? = nil
|
|
|
|
// 当前app所处的场景
|
|
var appScene: AppScene = .login(username: nil)
|
|
|
|
// 当前的场景
|
|
enum AppScene: Equatable {
|
|
case login(username: String?)
|
|
case logined
|
|
case register
|
|
case resetPassword
|
|
}
|
|
|
|
// 登陆凭证
|
|
var loginCredit: Credit?
|
|
|
|
// 判断用户是否登陆
|
|
var isLogined: Bool {
|
|
return loginCredit != nil
|
|
}
|
|
|
|
enum Credit {
|
|
case token(token: String, session: SDLAPIClient.NetworkSession)
|
|
case accountAndPasword(account: String, password: String, session: SDLAPIClient.NetworkSession)
|
|
}
|
|
|
|
@ObservationIgnored
|
|
var networkSession: SDLAPIClient.NetworkSession? {
|
|
guard let loginCredit = self.loginCredit else {
|
|
return nil
|
|
}
|
|
|
|
switch loginCredit {
|
|
case .token(_, let session):
|
|
return session
|
|
case .accountAndPasword(_, _, let session):
|
|
return session
|
|
}
|
|
}
|
|
|
|
init(noticePort: Int) {
|
|
self.noticePort = noticePort
|
|
}
|
|
|
|
func loginWith(token: String) async throws {
|
|
let networkSession = try await SDLAPIClient.loginWithToken(token: token)
|
|
self.loginCredit = .token(token: token, session: networkSession)
|
|
// 将数据缓存到keychain
|
|
if let data = token.data(using: .utf8) {
|
|
try KeychainStore.shared.save(data, account: "token")
|
|
}
|
|
}
|
|
|
|
func loginWith(username: String, password: String) async throws {
|
|
let networkSession = try await SDLAPIClient.loginWithAccountAndPassword(username: username, password: password)
|
|
self.loginCredit = .accountAndPasword(account: username, password: password, session: networkSession)
|
|
// 将数据缓存到keychain
|
|
if let data = "\(username):\(password)".data(using: .utf8) {
|
|
try KeychainStore.shared.save(data, account: "accountAndPasword")
|
|
}
|
|
}
|
|
|
|
// 连接到对应的网络
|
|
func connectNetwork() async throws {
|
|
guard let session = self.networkSession else {
|
|
throw AppContextError(message: "未登陆")
|
|
}
|
|
|
|
// 避免重复连接
|
|
guard !vpnManager.isConnected else {
|
|
throw AppContextError(message: "网络已经连接")
|
|
}
|
|
|
|
let context = try await SDLAPIClient.connectNetwork(accesToken: session.accessToken)
|
|
let options = SystemConfig.getOptions(
|
|
networkId: UInt32(session.networkId),
|
|
networkDomain: session.networkDomain,
|
|
ip: context.ip,
|
|
maskLen: context.maskLen,
|
|
accessToken: session.accessToken,
|
|
identityId: context.identityId,
|
|
hostname: context.hostname,
|
|
noticePort: noticePort
|
|
)
|
|
|
|
try await self.vpnManager.enableVpn(options: options)
|
|
self.networkContext = context
|
|
self.vpnOptions = options
|
|
|
|
// TODO
|
|
Task {
|
|
try await Task.sleep(for: .seconds(5))
|
|
let resp = try await self.vpnManager.sendMessage("hello vpn".data(using: .utf8)!)
|
|
NSLog("resp: \(String(data: resp, encoding: .utf8))")
|
|
}
|
|
}
|
|
|
|
// 断开网络连接
|
|
func disconnectNetwork() async throws {
|
|
try await self.vpnManager.disableVpn()
|
|
}
|
|
|
|
// 退出登陆
|
|
func logout() async throws {
|
|
try await self.vpnManager.disableVpn()
|
|
self.networkContext = .default()
|
|
self.loginCredit = nil
|
|
}
|
|
|
|
func loadCacheToken() -> String? {
|
|
if let data = try? KeychainStore.shared.load(account: "token") {
|
|
return String(data: data, encoding: .utf8)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func loadCacheUsernameAndPassword() -> (String, String)? {
|
|
if let data = try? KeychainStore.shared.load(account: "accountAndPasword"),
|
|
let str = String(data: data, encoding: .utf8) {
|
|
let parts = str.split(separator: ":")
|
|
if parts.count == 2 {
|
|
return (String(parts[0]), String(parts[1]))
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
}
|