core v1
This commit is contained in:
235
server/internal/handlers/handlers_network.go
Normal file
235
server/internal/handlers/handlers_network.go
Normal file
@@ -0,0 +1,235 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"server/internal/models"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func normalizeSSID(ssid string) string {
|
||||
return strings.TrimSpace(ssid)
|
||||
}
|
||||
|
||||
func ssidKey(ssid string) string {
|
||||
return strings.ToLower(strings.TrimSpace(ssid))
|
||||
}
|
||||
|
||||
func normalizeBSSID(bssid string) string {
|
||||
var hex []rune
|
||||
for _, c := range strings.ToLower(bssid) {
|
||||
if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') {
|
||||
hex = append(hex, c)
|
||||
}
|
||||
}
|
||||
if len(hex) != 12 {
|
||||
return strings.TrimSpace(bssid)
|
||||
}
|
||||
s := string(hex)
|
||||
return s[0:2] + ":" + s[2:4] + ":" + s[4:6] + ":" + s[6:8] + ":" + s[8:10] + ":" + s[10:12]
|
||||
}
|
||||
|
||||
func bssidKey(bssid string) string {
|
||||
var hex []rune
|
||||
for _, c := range strings.ToLower(bssid) {
|
||||
if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') {
|
||||
hex = append(hex, c)
|
||||
}
|
||||
}
|
||||
return string(hex)
|
||||
}
|
||||
|
||||
type wifiItemPayload struct {
|
||||
SSID string `json:"ssid"`
|
||||
BSSID string `json:"bssid"`
|
||||
}
|
||||
|
||||
// POST /api/student/report-wifi — ghi nhận SSID + BSSID vào kho
|
||||
func ReportWifiHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
var req struct {
|
||||
StudentRkID int64 `json:"studentRkId"`
|
||||
SSID string `json:"ssid"`
|
||||
BSSID string `json:"bssid"`
|
||||
}
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid payload"})
|
||||
}
|
||||
ssid := normalizeSSID(req.SSID)
|
||||
bssid := normalizeBSSID(req.BSSID)
|
||||
sKey := ssidKey(ssid)
|
||||
bKey := bssidKey(bssid)
|
||||
if sKey == "" || bKey == "" || len(bKey) != 12 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "ssid and valid bssid are required"})
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
var row models.WifiPoolEntry
|
||||
err := db.Where("bssid_key = ?", bKey).First(&row).Error
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
row = models.WifiPoolEntry{
|
||||
SSID: ssid,
|
||||
SSIDKey: sKey,
|
||||
BSSID: bssid,
|
||||
BSSIDKey: bKey,
|
||||
HitCount: 1,
|
||||
LastSeenAt: now,
|
||||
LastStudentRkID: req.StudentRkID,
|
||||
}
|
||||
if err := db.Create(&row).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
} else if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
} else {
|
||||
row.HitCount++
|
||||
row.LastSeenAt = now
|
||||
row.SSID = ssid
|
||||
row.SSIDKey = sKey
|
||||
row.BSSID = bssid
|
||||
if req.StudentRkID > 0 {
|
||||
row.LastStudentRkID = req.StudentRkID
|
||||
}
|
||||
if err := db.Save(&row).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true, "data": row})
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/student/wifi-policy — danh sách điểm phát được phép (theo BSSID)
|
||||
func GetStudentWifiPolicyHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
var rows []models.AcceptedWifi
|
||||
if err := db.Where("bssid_key <> '' AND LENGTH(bssid_key) = 12").Order("ssid asc").Find(&rows).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
items := make([]wifiItemPayload, 0, len(rows))
|
||||
for _, r := range rows {
|
||||
items = append(items, wifiItemPayload{SSID: r.SSID, BSSID: r.BSSID})
|
||||
}
|
||||
return c.JSON(fiber.Map{
|
||||
"enforce": len(items) > 0,
|
||||
"accepted": items,
|
||||
"acceptedSsids": nil, // legacy — client mới dùng accepted
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/wifi-pool?q=&limit=
|
||||
func ListWifiPoolHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
q := strings.TrimSpace(c.Query("q", ""))
|
||||
limit := 50
|
||||
if l, err := strconv.Atoi(c.Query("limit", "50")); err == nil && l > 0 && l <= 200 {
|
||||
limit = l
|
||||
}
|
||||
query := db.Model(&models.WifiPoolEntry{}).Where("bssid_key <> '' AND LENGTH(bssid_key) = 12")
|
||||
if q != "" {
|
||||
like := "%" + q + "%"
|
||||
query = query.Where("ssid LIKE ? OR ssid_key LIKE ? OR bssid LIKE ? OR bssid_key LIKE ?", like, like, like, like)
|
||||
}
|
||||
var rows []models.WifiPoolEntry
|
||||
if err := query.Order("hit_count DESC, last_seen_at DESC").Limit(limit).Find(&rows).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"data": rows, "q": q, "limit": limit})
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/network/accepted-wifis
|
||||
func ListAcceptedWifisHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
var rows []models.AcceptedWifi
|
||||
if err := db.Order("ssid asc, bssid asc").Find(&rows).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"data": rows})
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/network/accepted-wifis — thay toàn bộ danh sách (cần SSID + BSSID)
|
||||
func SaveAcceptedWifisHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
var req struct {
|
||||
Items []wifiItemPayload `json:"items"`
|
||||
}
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid payload"})
|
||||
}
|
||||
if err := db.Where("1 = 1").Delete(&models.AcceptedWifi{}).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
now := time.Now()
|
||||
count := 0
|
||||
seen := map[string]bool{}
|
||||
for _, item := range req.Items {
|
||||
ssid := normalizeSSID(item.SSID)
|
||||
bssid := normalizeBSSID(item.BSSID)
|
||||
sKey := ssidKey(ssid)
|
||||
bKey := bssidKey(bssid)
|
||||
if sKey == "" || bKey == "" || len(bKey) != 12 || seen[bKey] {
|
||||
continue
|
||||
}
|
||||
seen[bKey] = true
|
||||
if err := db.Create(&models.AcceptedWifi{
|
||||
SSID: ssid,
|
||||
SSIDKey: sKey,
|
||||
BSSID: bssid,
|
||||
BSSIDKey: bKey,
|
||||
CreatedAt: now,
|
||||
}).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
count++
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true, "count": count})
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/network/accepted-wifis/add
|
||||
func AddAcceptedWifiHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
var req wifiItemPayload
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Invalid payload"})
|
||||
}
|
||||
ssid := normalizeSSID(req.SSID)
|
||||
bssid := normalizeBSSID(req.BSSID)
|
||||
sKey := ssidKey(ssid)
|
||||
bKey := bssidKey(bssid)
|
||||
if sKey == "" || bKey == "" || len(bKey) != 12 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "ssid and valid bssid are required"})
|
||||
}
|
||||
row := models.AcceptedWifi{
|
||||
SSID: ssid,
|
||||
SSIDKey: sKey,
|
||||
BSSID: bssid,
|
||||
BSSIDKey: bKey,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
if err := db.Where("bssid_key = ?", bKey).FirstOrCreate(&row).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true, "data": row})
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE /api/network/accepted-wifis/:id
|
||||
func DeleteAcceptedWifiHandler(db *gorm.DB) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
id, err := strconv.ParseUint(c.Params("id"), 10, 64)
|
||||
if err != nil || id == 0 {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "invalid id"})
|
||||
}
|
||||
if err := db.Delete(&models.AcceptedWifi{}, id).Error; err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": err.Error()})
|
||||
}
|
||||
return c.JSON(fiber.Map{"ok": true})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user