236 lines
7.2 KiB
Go
236 lines
7.2 KiB
Go
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})
|
|
}
|
|
}
|