158 lines
4.9 KiB
Swift
158 lines
4.9 KiB
Swift
//
|
|
// LoginState.swift
|
|
// punchnet
|
|
//
|
|
// Created by 安礼成 on 2026/1/16.
|
|
//
|
|
|
|
import Foundation
|
|
import Observation
|
|
|
|
@Observable
|
|
class UserContext {
|
|
var loginCredit: Credit?
|
|
var networkSession: NetworkSession?
|
|
|
|
enum Credit {
|
|
case token(token: String)
|
|
case accountAndPasword(account: String, password: String)
|
|
}
|
|
|
|
// 登陆后的网络会话信息
|
|
struct NetworkSession: Codable {
|
|
struct ExitNode: Codable {
|
|
let uuid = UUID().uuidString
|
|
let nnid: Int
|
|
let nodeName: String
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case nnid
|
|
case nodeName = "node_name"
|
|
}
|
|
}
|
|
|
|
let accessToken: String
|
|
let username: String
|
|
let userType: String
|
|
let audit: Int
|
|
let networkId: Int
|
|
let networkName: String
|
|
let networkDomain: String
|
|
let exitNodes: [ExitNode]
|
|
|
|
var networkUrl: String {
|
|
return "https://www.test.cn/id=\(self.networkId)"
|
|
}
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case accessToken = "access_token"
|
|
case username
|
|
case userType = "user_type"
|
|
case audit
|
|
case networkId = "network_id"
|
|
case networkName = "network_name"
|
|
case networkDomain = "network_domain"
|
|
case exitNodes = "exit_node"
|
|
}
|
|
}
|
|
|
|
private let baseParams: [String: Any] = [
|
|
"client_id": SystemConfig.getClientId(),
|
|
"mac": SystemConfig.macAddressString(mac: SystemConfig.getMacAddress())
|
|
]
|
|
|
|
@MainActor
|
|
func loginWithAccountAndPassword(username: String, password: String) async throws -> Bool {
|
|
var params: [String: Any] = [
|
|
"username": username,
|
|
"password": password,
|
|
"system": SystemConfig.systemInfo,
|
|
"version": SystemConfig.version_name
|
|
]
|
|
params.merge(baseParams) {$1}
|
|
|
|
self.networkSession = try await SDLAPIClient.doPost(path: "/auth/login", params: params, as: NetworkSession.self)
|
|
self.loginCredit = .accountAndPasword(account: username, password: password)
|
|
|
|
// 将数据缓存到keychain
|
|
if let data = "\(username):\(password)".data(using: .utf8) {
|
|
try KeychainStore.shared.save(data, account: "accountAndPasword")
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
@MainActor
|
|
func loginWithToken(token: String) async throws -> Bool {
|
|
var params: [String: Any] = [
|
|
"token": token,
|
|
"system": SystemConfig.systemInfo,
|
|
"version": SystemConfig.version_name
|
|
]
|
|
params.merge(baseParams) {$1}
|
|
|
|
self.networkSession = try await SDLAPIClient.doPost(path: "/auth/token", params: params, as: NetworkSession.self)
|
|
self.loginCredit = .token(token: token)
|
|
|
|
// 将数据缓存到keychain
|
|
if let data = token.data(using: .utf8) {
|
|
try KeychainStore.shared.save(data, account: "token")
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// func sendVerifyCode(username: String) async throws -> String {
|
|
// var params: [String: Any] = [
|
|
// "username": username
|
|
// ]
|
|
// params.merge(baseParams) {$1}
|
|
//
|
|
// return try await SDLAPIClient.doPost(path: "/auth/sendVerifyCode", params: params, as: String.self)
|
|
// }
|
|
//
|
|
// func submitVerifyCode(username: String, verifyCode: String) async throws -> String {
|
|
// var params: [String: Any] = [
|
|
// "username": username,
|
|
// "verify_code": verifyCode,
|
|
// ]
|
|
// params.merge(baseParams) {$1}
|
|
//
|
|
// return try await SDLAPIClient.doPost(path: "/auth/submitVerifyCode", params: params, as: String.self)
|
|
// }
|
|
//
|
|
// func resetPassword(username: String, password: String) async throws -> String {
|
|
// var params: [String: Any] = [
|
|
// "username": username,
|
|
// "password": password,
|
|
// ]
|
|
// params.merge(baseParams) {$1}
|
|
//
|
|
// return try await SDLAPIClient.doPost(path: "/auth/resetPassword", params: params, as: String.self)
|
|
// }
|
|
|
|
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
|
|
}
|
|
|
|
// 退出登陆
|
|
func logout() async throws {
|
|
try await VPNManager.shared.disableVpn()
|
|
}
|
|
|
|
}
|