add macos
This commit is contained in:
BIN
client/.DS_Store
vendored
BIN
client/.DS_Store
vendored
Binary file not shown.
@@ -126,6 +126,7 @@ type App struct {
|
|||||||
streamScStop chan struct{}
|
streamScStop chan struct{}
|
||||||
statusMsg string
|
statusMsg string
|
||||||
expectingLogin bool
|
expectingLogin bool
|
||||||
|
needsClearPortalStorage bool
|
||||||
backendOnline bool
|
backendOnline bool
|
||||||
dashboard StudentDashboardSnapshot
|
dashboard StudentDashboardSnapshot
|
||||||
wifiEnforce bool
|
wifiEnforce bool
|
||||||
@@ -209,6 +210,9 @@ func (a *App) startup(ctx context.Context) {
|
|||||||
a.loadSession()
|
a.loadSession()
|
||||||
a.loadStats()
|
a.loadStats()
|
||||||
|
|
||||||
|
// Request Location Access (macOS)
|
||||||
|
winapi.RequestLocationAccess()
|
||||||
|
|
||||||
// Register blocker callbacks
|
// Register blocker callbacks
|
||||||
blocker.Instance.OnBlocked = func(procName string, title string) {
|
blocker.Instance.OnBlocked = func(procName string, title string) {
|
||||||
go a.reportBlockedApp(procName, title)
|
go a.reportBlockedApp(procName, title)
|
||||||
@@ -534,7 +538,8 @@ func (a *App) NavigateToLogin() {
|
|||||||
func (a *App) Logout() {
|
func (a *App) Logout() {
|
||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
a.student = nil
|
a.student = nil
|
||||||
a.expectingLogin = false
|
a.expectingLogin = true
|
||||||
|
a.needsClearPortalStorage = true
|
||||||
a.mu.Unlock()
|
a.mu.Unlock()
|
||||||
|
|
||||||
_ = os.Remove(a.sessionPath)
|
_ = os.Remove(a.sessionPath)
|
||||||
@@ -552,7 +557,7 @@ func (a *App) Logout() {
|
|||||||
a.stopScreenshotStream()
|
a.stopScreenshotStream()
|
||||||
|
|
||||||
guard.SuppressFor(5 * time.Second)
|
guard.SuppressFor(5 * time.Second)
|
||||||
runtime.WindowReloadApp(a.ctx)
|
runtime.WindowExecJS(a.ctx, "window.location.href = 'https://portal.rikkei.edu.vn/dangnhap'")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStats trả về Wifi, thời gian online/offline và trạng thái giám sát
|
// GetStats trả về Wifi, thời gian online/offline và trạng thái giám sát
|
||||||
@@ -622,9 +627,23 @@ func (a *App) authStorageScanner() {
|
|||||||
|
|
||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
expecting := a.expectingLogin
|
expecting := a.expectingLogin
|
||||||
|
needsClear := a.needsClearPortalStorage
|
||||||
loggedIn := a.student != nil
|
loggedIn := a.student != nil
|
||||||
a.mu.Unlock()
|
a.mu.Unlock()
|
||||||
|
|
||||||
|
if needsClear && expecting {
|
||||||
|
runtime.WindowExecJS(a.ctx, `
|
||||||
|
try {
|
||||||
|
localStorage.removeItem("student");
|
||||||
|
localStorage.removeItem("token");
|
||||||
|
} catch(e) {}
|
||||||
|
`)
|
||||||
|
a.mu.Lock()
|
||||||
|
a.needsClearPortalStorage = false
|
||||||
|
a.mu.Unlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if loggedIn || !expecting {
|
if loggedIn || !expecting {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -661,8 +680,16 @@ func (a *App) runMonitorTick() {
|
|||||||
|
|
||||||
wifi := winapi.GetWifiConnection()
|
wifi := winapi.GetWifiConnection()
|
||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
|
if strings.Contains(strings.ToLower(wifi.SSID), "redacted") {
|
||||||
|
a.wifiSSID = "Chưa cấp quyền Vị Trí (macOS)"
|
||||||
|
} else {
|
||||||
a.wifiSSID = wifi.SSID
|
a.wifiSSID = wifi.SSID
|
||||||
|
}
|
||||||
|
if strings.Contains(strings.ToLower(wifi.BSSID), "redacted") {
|
||||||
|
a.wifiBSSID = "Chưa cấp quyền Vị Trí (macOS)"
|
||||||
|
} else {
|
||||||
a.wifiBSSID = wifi.BSSID
|
a.wifiBSSID = wifi.BSSID
|
||||||
|
}
|
||||||
a.mu.Unlock()
|
a.mu.Unlock()
|
||||||
|
|
||||||
backendOnline := a.pingBackend()
|
backendOnline := a.pingBackend()
|
||||||
@@ -732,8 +759,16 @@ func (a *App) refreshNetworkStatus() {
|
|||||||
wifi := winapi.GetWifiConnection()
|
wifi := winapi.GetWifiConnection()
|
||||||
backendOnline := a.pingBackend()
|
backendOnline := a.pingBackend()
|
||||||
a.mu.Lock()
|
a.mu.Lock()
|
||||||
|
if strings.Contains(strings.ToLower(wifi.SSID), "redacted") {
|
||||||
|
a.wifiSSID = "Chưa cấp quyền Vị Trí (macOS)"
|
||||||
|
} else {
|
||||||
a.wifiSSID = wifi.SSID
|
a.wifiSSID = wifi.SSID
|
||||||
|
}
|
||||||
|
if strings.Contains(strings.ToLower(wifi.BSSID), "redacted") {
|
||||||
|
a.wifiBSSID = "Chưa cấp quyền Vị Trí (macOS)"
|
||||||
|
} else {
|
||||||
a.wifiBSSID = wifi.BSSID
|
a.wifiBSSID = wifi.BSSID
|
||||||
|
}
|
||||||
a.backendOnline = backendOnline
|
a.backendOnline = backendOnline
|
||||||
a.mu.Unlock()
|
a.mu.Unlock()
|
||||||
if backendOnline {
|
if backendOnline {
|
||||||
@@ -923,6 +958,10 @@ func (a *App) isWifiAllowed(ssid, bssid string) bool {
|
|||||||
if !enforce || len(allowed) == 0 {
|
if !enforce || len(allowed) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// Bypass Wi-Fi check if it's redacted by macOS privacy controls
|
||||||
|
if strings.Contains(strings.ToLower(ssid), "redacted") || strings.Contains(strings.ToLower(bssid), "redacted") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
bKey := winapi.BSSIDKey(bssid)
|
bKey := winapi.BSSIDKey(bssid)
|
||||||
if bKey == "" || len(bKey) != 12 {
|
if bKey == "" || len(bKey) != 12 {
|
||||||
return false
|
return false
|
||||||
|
|||||||
BIN
client/build/.DS_Store
vendored
BIN
client/build/.DS_Store
vendored
Binary file not shown.
@@ -64,5 +64,7 @@
|
|||||||
<key>NSAllowsLocalNetworking</key>
|
<key>NSAllowsLocalNetworking</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
|
<string>Ứng dụng cần quyền vị trí để xác thực mạng Wi-Fi phòng thi.</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -59,5 +59,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
</array>
|
</array>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
<key>NSLocationWhenInUseUsageDescription</key>
|
||||||
|
<string>Ứng dụng cần quyền vị trí để xác thực mạng Wi-Fi phòng thi.</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -2,45 +2,52 @@
|
|||||||
|
|
||||||
package winapi
|
package winapi
|
||||||
|
|
||||||
|
/*
|
||||||
|
#cgo LDFLAGS: -framework CoreWLAN -framework CoreLocation -framework Foundation
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* ssid;
|
||||||
|
char* bssid;
|
||||||
|
} CWifiInfo;
|
||||||
|
|
||||||
|
void RequestLocationPermission();
|
||||||
|
CWifiInfo GetCurrentWifiInfo();
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"unsafe"
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetWifiConnection đọc SSID và BSSID từ ipconfig (macOS)
|
// RequestLocationAccess requests Location permission on macOS
|
||||||
|
func RequestLocationAccess() {
|
||||||
|
C.RequestLocationPermission()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWifiConnection đọc SSID và BSSID từ CoreWLAN (macOS)
|
||||||
func GetWifiConnection() WifiConnection {
|
func GetWifiConnection() WifiConnection {
|
||||||
// Find Wi-Fi interface dynamically
|
info := C.GetCurrentWifiInfo()
|
||||||
wifiInterface := "en0"
|
defer func() {
|
||||||
cmdPort := exec.Command("networksetup", "-listallhardwareports")
|
if info.ssid != nil {
|
||||||
if outPort, err := cmdPort.Output(); err == nil {
|
C.free(unsafe.Pointer(info.ssid))
|
||||||
lines := strings.Split(string(outPort), "\n")
|
|
||||||
for i := 0; i < len(lines)-1; i++ {
|
|
||||||
if strings.Contains(lines[i], "Hardware Port: Wi-Fi") {
|
|
||||||
next := strings.TrimSpace(lines[i+1])
|
|
||||||
if strings.HasPrefix(next, "Device:") {
|
|
||||||
wifiInterface = strings.TrimSpace(strings.TrimPrefix(next, "Device:"))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if info.bssid != nil {
|
||||||
|
C.free(unsafe.Pointer(info.bssid))
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
ssid := ""
|
||||||
|
if info.ssid != nil {
|
||||||
|
ssid = C.GoString(info.ssid)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command("ipconfig", "getsummary", wifiInterface)
|
bssid := ""
|
||||||
var out bytes.Buffer
|
if info.bssid != nil {
|
||||||
cmd.Stdout = &out
|
bssid = C.GoString(info.bssid)
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
return WifiConnection{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var conn WifiConnection
|
return WifiConnection{
|
||||||
for _, line := range strings.Split(out.String(), "\n") {
|
SSID: ssid,
|
||||||
trimmed := strings.TrimSpace(line)
|
BSSID: normalizeMAC(bssid),
|
||||||
if strings.HasPrefix(trimmed, "SSID :") {
|
|
||||||
conn.SSID = strings.TrimSpace(strings.TrimPrefix(trimmed, "SSID :"))
|
|
||||||
} else if strings.HasPrefix(trimmed, "BSSID :") {
|
|
||||||
conn.BSSID = normalizeMAC(strings.TrimSpace(strings.TrimPrefix(trimmed, "BSSID :")))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return conn
|
|
||||||
}
|
|
||||||
|
|||||||
45
client/internal/winapi/wifi_darwin.m
Normal file
45
client/internal/winapi/wifi_darwin.m
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#import <CoreWLAN/CoreWLAN.h>
|
||||||
|
#import <CoreLocation/CoreLocation.h>
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
static CLLocationManager *locationManager = nil;
|
||||||
|
|
||||||
|
void RequestLocationPermission() {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (locationManager == nil) {
|
||||||
|
locationManager = [[CLLocationManager alloc] init];
|
||||||
|
}
|
||||||
|
if (@available(macOS 10.15, *)) {
|
||||||
|
[locationManager requestWhenInUseAuthorization];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char* ssid;
|
||||||
|
char* bssid;
|
||||||
|
} CWifiInfo;
|
||||||
|
|
||||||
|
CWifiInfo GetCurrentWifiInfo() {
|
||||||
|
CWifiInfo info;
|
||||||
|
info.ssid = NULL;
|
||||||
|
info.bssid = NULL;
|
||||||
|
|
||||||
|
@autoreleasepool {
|
||||||
|
CWWiFiClient *client = [CWWiFiClient sharedWiFiClient];
|
||||||
|
if (client != nil) {
|
||||||
|
CWInterface *interface = [client interface];
|
||||||
|
if (interface != nil) {
|
||||||
|
NSString *ssidStr = [interface ssid];
|
||||||
|
NSString *bssidStr = [interface bssid];
|
||||||
|
if (ssidStr != nil) {
|
||||||
|
info.ssid = strdup([ssidStr UTF8String]);
|
||||||
|
}
|
||||||
|
if (bssidStr != nil) {
|
||||||
|
info.bssid = strdup([bssidStr UTF8String]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
@@ -6,3 +6,6 @@ package winapi
|
|||||||
func GetWifiConnection() WifiConnection {
|
func GetWifiConnection() WifiConnection {
|
||||||
return WifiConnection{}
|
return WifiConnection{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequestLocationAccess requests Location permission (stub for other systems)
|
||||||
|
func RequestLocationAccess() {}
|
||||||
|
|||||||
@@ -38,3 +38,6 @@ func GetWifiConnection() WifiConnection {
|
|||||||
}
|
}
|
||||||
return conn
|
return conn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RequestLocationAccess requests Location permission (stub for Windows)
|
||||||
|
func RequestLocationAccess() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user