Files
3m-ui/backend/internal/user/user_test.go
T
風雪 0f234c0efe fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
fix(protocol): restore broken share_modules.go and implement VLESS BuildShare
The previous commit 658ef5c left share_modules.go starting with 'if'
instead of 'package protocol', making the whole module unbuildable.
This restores:
- package declaration and imports
- Trojan / Shadowsocks / Hysteria2 BuildShare methods
- the missing VLESSCompiler.BuildShare (expected by share_reality_test.go)
Also fixes reality public-key encoding in node/uri_builders.go to use
RawURLEncoding (URL-safe) consistently, matching protocol expectations.
Fixes: 658ef5c (build was broken)
2026-08-29 09:38:25 +00:00

152 lines
4.2 KiB
Go

package user
import (
"fmt"
"testing"
"time"
"github.com/kazeyukiro/3m-ui/backend/internal/database"
"github.com/kazeyukiro/3m-ui/backend/internal/database/models"
"github.com/kazeyukiro/3m-ui/backend/internal/security"
)
func TestActiveCredentialsFiltering(t *testing.T) {
security.InitCredentialKey("test-secret")
db, err := database.InitDB(t.TempDir() + "/test.db")
if err != nil {
t.Fatal(err)
}
svc := NewService(db)
l1 := models.Listener{Name: "ss", Protocol: "shadowsocks", Port: "8388", Enabled: true}
if err := db.Create(&l1).Error; err != nil {
t.Fatal(err)
}
active, err := svc.Create(CreateInput{Username: "active", Password: "p1"})
if err != nil {
t.Fatal(err)
}
expiredAt := time.Now().Add(-time.Hour)
expired, err := svc.Create(CreateInput{Username: "expired", Password: "p2", ExpireTime: &expiredAt})
if err != nil {
t.Fatal(err)
}
limited, err := svc.Create(CreateInput{Username: "limited", Password: "p3", TrafficLimit: 10})
if err != nil {
t.Fatal(err)
}
if err := db.Model(limited).Update("traffic_used", int64(10)).Error; err != nil {
t.Fatal(err)
}
for _, id := range []uint{active.ID, expired.ID, limited.ID} {
if err := db.Create(&models.ListenerUser{ListenerID: l1.ID, ProxyUserID: id}).Error; err != nil {
t.Fatal(err)
}
}
creds, err := svc.ActiveCredentialsByListener()
if err != nil {
t.Fatal(err)
}
if len(creds[l1.ID]) != 1 || creds[l1.ID][0].Password != "p1" {
t.Fatalf("expected only active user credential, got %#v", creds[l1.ID])
}
}
func TestBindListenersIsReplacement(t *testing.T) {
security.InitCredentialKey("test-secret")
db, err := database.InitDB(t.TempDir() + "/test.db")
if err != nil {
t.Fatal(err)
}
svc := NewService(db)
u, err := svc.Create(CreateInput{Username: "bind-user", Password: "p"})
if err != nil {
t.Fatal(err)
}
var listeners []models.Listener
for i := 0; i < 3; i++ {
l := models.Listener{Name: fmt.Sprintf("n-%d", i), Protocol: "trojan", Port: fmt.Sprintf("%d", 10000+i), Enabled: true}
if err := db.Create(&l).Error; err != nil {
t.Fatal(err)
}
listeners = append(listeners, l)
}
if err := svc.BindListeners(u.ID, []uint{listeners[0].ID, listeners[1].ID}); err != nil {
t.Fatal(err)
}
if err := svc.BindListeners(u.ID, []uint{listeners[2].ID}); err != nil {
t.Fatal(err)
}
got, err := svc.GetListeners(u.ID)
if err != nil {
t.Fatal(err)
}
if len(got) != 1 || got[0].ID != listeners[2].ID {
t.Fatalf("expected replacement binding, got %#v", got)
}
if err := svc.BindListeners(u.ID, []uint{listeners[2].ID, listeners[2].ID, listeners[0].ID}); err != nil {
t.Fatal(err)
}
got, err = svc.GetListeners(u.ID)
if err != nil {
t.Fatal(err)
}
if len(got) != 2 || got[0].ID != listeners[0].ID || got[1].ID != listeners[2].ID {
t.Fatalf("expected deduplicated replacement binding, got %#v", got)
}
var rows []models.ListenerUser
if err := db.Unscoped().Where("proxy_user_id = ?", u.ID).Find(&rows).Error; err != nil {
t.Fatal(err)
}
if len(rows) != 3 {
t.Fatalf("expected soft-deleted bindings to be reused without duplicates, got %#v", rows)
}
}
func TestDeleteDepletedKeepsDisabled(t *testing.T) {
security.InitCredentialKey("test-secret")
db, err := database.InitDB(t.TempDir() + "/test-del.db")
if err != nil {
t.Fatal(err)
}
svc := NewService(db)
active, err := svc.Create(CreateInput{Username: "keep-active", Password: "p1"})
if err != nil {
t.Fatal(err)
}
disabled, err := svc.Create(CreateInput{Username: "keep-disabled", Password: "p2", Enabled: boolPtr(false)})
if err != nil {
t.Fatal(err)
}
expiredAt := time.Now().Add(-time.Hour)
expired, err := svc.Create(CreateInput{Username: "del-expired", Password: "p3", ExpireTime: &expiredAt})
if err != nil {
t.Fatal(err)
}
n, err := svc.DeleteDepleted()
if err != nil {
t.Fatal(err)
}
if n != 1 {
t.Fatalf("expected 1 deleted (expired only), got %d", n)
}
if _, err := svc.GetByID(active.ID); err != nil {
t.Fatalf("active user should remain: %v", err)
}
if _, err := svc.GetByID(disabled.ID); err != nil {
t.Fatalf("disabled user should remain: %v", err)
}
if _, err := svc.GetByID(expired.ID); err == nil {
t.Fatal("expired user should be deleted")
}
}
func boolPtr(v bool) *bool { return &v }