snapshot of https://github.com/traggo/server.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
build / build (push) Failing after 3s

This commit is contained in:
upstream-mirror
2026-09-16 05:24:45 +05:00
commit cda7c1a474
272 changed files with 31973 additions and 0 deletions

28
user/create.go Normal file
View File

@@ -0,0 +1,28 @@
package user
import (
"context"
"fmt"
"github.com/jinzhu/copier"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// CreateUser creates a user.
func (r *ResolverForUser) CreateUser(ctx context.Context, name string, pass string, admin bool) (*gqlmodel.User, error) {
newUser := &model.User{
Name: name,
Pass: createPassword(pass, r.PassStrength),
Admin: admin,
}
if !r.DB.Where("name = ?", newUser.Name).Find(&model.User{}).RecordNotFound() {
return nil, fmt.Errorf("user with name '%s' does already exist", newUser.Name)
}
create := r.DB.Create(&newUser)
gqlUser := &gqlmodel.User{}
copier.Copy(gqlUser, newUser)
return gqlUser, create.Error
}

52
user/create_test.go Normal file
View File

@@ -0,0 +1,52 @@
package user
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
"github.com/traggo/server/test"
)
func TestGQL_CreateUser_succeeds_addsUser(t *testing.T) {
createPassword = fakePassword
db := test.InMemoryDB(t)
defer db.Close()
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
user, err := resolver.CreateUser(context.Background(), "jmattheis", "unicorn", true)
require.Nil(t, err)
expected := &gqlmodel.User{
Name: "jmattheis",
Admin: true,
ID: 1,
}
require.Equal(t, expected, user)
assertUserExist(t, db, model.User{
Name: "jmattheis",
Pass: unicornPW,
ID: 1,
Admin: true,
})
assertUserCount(t, db, 1)
}
func TestGQL_CreateUser_fails_userAlreadyExists(t *testing.T) {
createPassword = fakePassword
db := test.InMemoryDB(t)
defer db.Close()
db.Create(&model.User{
Name: "jmattheis",
Pass: unicornPW,
ID: 1,
Admin: true,
})
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
_, err := resolver.CreateUser(context.Background(), "jmattheis", "unicorn", true)
require.EqualError(t, err, "user with name 'jmattheis' does already exist")
assertUserCount(t, db, 1)
}

20
user/current.go Normal file
View File

@@ -0,0 +1,20 @@
package user
import (
"context"
"github.com/jinzhu/copier"
"github.com/traggo/server/auth"
"github.com/traggo/server/generated/gqlmodel"
)
// CurrentUser returns the current user.
func (r *ResolverForUser) CurrentUser(ctx context.Context) (*gqlmodel.User, error) {
user := auth.GetUser(ctx)
if user == nil {
return nil, nil
}
var result gqlmodel.User
copier.Copy(&result, user)
return &result, nil
}

39
user/current_test.go Normal file
View File

@@ -0,0 +1,39 @@
package user
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/test"
"github.com/traggo/server/test/fake"
)
func TestGQL_CurrentUser_withUser(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
resolver := ResolverForUser{DB: db.DB}
result, err := resolver.CurrentUser(fake.UserWithPerm(2, true))
require.Nil(t, err)
expected := &gqlmodel.User{
ID: 2,
Name: "fake",
Admin: true,
}
require.Equal(t, expected, result)
}
func TestGQL_CurrentUser_noUser(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
resolver := ResolverForUser{DB: db.DB}
result, err := resolver.CurrentUser(context.Background())
require.Nil(t, err)
require.Nil(t, result)
}

18
user/get.go Normal file
View File

@@ -0,0 +1,18 @@
package user
import (
"context"
"github.com/jinzhu/copier"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// Users returns all users.
func (r *ResolverForUser) Users(ctx context.Context) ([]*gqlmodel.User, error) {
var users []model.User
find := r.DB.Find(&users)
var result []*gqlmodel.User
copier.Copy(&result, &users)
return result, find.Error
}

35
user/get_test.go Normal file
View File

@@ -0,0 +1,35 @@
package user
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/test"
)
func TestGQL_Users(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
db.NewUserPass(1, "jmattheis", unicornPW, true)
db.NewUserPass(2, "broderpeters", ponyPW, false)
users, err := resolver.Users(context.Background())
require.Nil(t, err)
expected := []*gqlmodel.User{
{
Name: "jmattheis",
ID: 1,
Admin: true,
},
{
Name: "broderpeters",
ID: 2,
Admin: false,
},
}
require.Equal(t, expected, users)
}

17
user/password/password.go Normal file
View File

@@ -0,0 +1,17 @@
package password
import "golang.org/x/crypto/bcrypt"
// CreatePassword returns a hashed version of the given password.
func CreatePassword(pw string, strength int) []byte {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(pw), strength)
if err != nil {
panic(err)
}
return hashedPassword
}
// ComparePassword compares a hashed password with its possible plaintext equivalent.
func ComparePassword(hashedPassword, password []byte) bool {
return bcrypt.CompareHashAndPassword(hashedPassword, password) == nil
}

View File

@@ -0,0 +1,21 @@
package password
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestPasswordSuccess(t *testing.T) {
password := CreatePassword("secret", 4)
assert.Equal(t, true, ComparePassword(password, []byte("secret")))
}
func TestPasswordFailure(t *testing.T) {
password := CreatePassword("secret", 4)
assert.Equal(t, false, ComparePassword(password, []byte("secretx")))
}
func TestBCryptFailure(t *testing.T) {
assert.Panics(t, func() { CreatePassword("secret", 12312) })
}

23
user/remove.go Normal file
View File

@@ -0,0 +1,23 @@
package user
import (
"context"
"fmt"
"github.com/jinzhu/copier"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// RemoveUser removes a user
func (r *ResolverForUser) RemoveUser(ctx context.Context, id int) (*gqlmodel.User, error) {
user := model.User{ID: id}
if r.DB.Find(&user).RecordNotFound() {
return nil, fmt.Errorf("user with id %d does not exist", user.ID)
}
remove := r.DB.Delete(&user)
gqlUser := &gqlmodel.User{}
copier.Copy(gqlUser, &user)
return gqlUser, remove.Error
}

104
user/remove_test.go Normal file
View File

@@ -0,0 +1,104 @@
package user
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/test"
)
func TestGQL_RemoveUser_succeeds_removesUser(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.NewUserPass(1, "jmattheis", unicornPW, true)
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
_, err := resolver.RemoveUser(context.Background(), 1)
require.Nil(t, err)
assertUserCount(t, db, 0)
}
func TestGQL_RemoveUser_succeeds_removesDevices(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
user := db.User(1)
user.NewDevice(2, "abc", "devicename")
other := db.User(2)
other.NewDevice(5, "abcx", "devicename")
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
_, err := resolver.RemoveUser(context.Background(), 1)
require.Nil(t, err)
user.AssertHasDevice("devicename", false).AssertExists(false)
other.AssertExists(true).AssertHasDevice("devicename", true)
}
func TestGQL_RemoveUser_succeeds_removesTags(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
user := db.User(1)
user.NewTagDefinition("oops")
other := db.User(2)
other.NewTagDefinition("oops")
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
_, err := resolver.RemoveUser(context.Background(), 1)
require.Nil(t, err)
user.AssertExists(false).AssertHasTagDefinition("oops", false)
other.AssertExists(true).AssertHasTagDefinition("oops", true)
}
func TestGQL_RemoveUser_succeeds_removesTimeSpans(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
user := db.User(1)
other := db.User(2)
ts := user.TimeSpan("2019-06-11T18:00:00Z", "2019-06-11T18:00:00Z")
ts.Tag("hello", "world")
otherTs := other.TimeSpan("2019-06-11T18:00:00Z", "2019-06-11T18:00:00Z")
otherTs.Tag("hello", "world")
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
_, err := resolver.RemoveUser(context.Background(), 1)
require.Nil(t, err)
ts.AssertExists(false).AssertHasTag("hello", "world", false)
otherTs.AssertExists(true).AssertHasTag("hello", "world", true)
}
func TestGQL_RemoveUser_succeeds_removesDashboard(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
user := db.User(1)
other := db.User(2)
userDB := user.Dashboard("cool")
userDB.Range("cool range")
userDB.Entry("cool entry")
otherDB := other.Dashboard("cool")
otherDB.Range("cool range")
otherDB.Entry("cool entry")
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
_, err := resolver.RemoveUser(context.Background(), 1)
require.Nil(t, err)
userDB.AssertExists(false).AssertHasRange("cool range", false).AssertHasEntry("cool entry", false)
otherDB.AssertExists(true).AssertHasRange("cool range", true).AssertHasEntry("cool entry", true)
}
func TestGQL_RemoveUser_fails_notExistingUser(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.NewUserPass(1, "jmattheis", unicornPW, true)
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
_, err := resolver.RemoveUser(context.Background(), 3)
require.EqualError(t, err, "user with id 3 does not exist")
assertUserCount(t, db, 1)
}

30
user/update.go Normal file
View File

@@ -0,0 +1,30 @@
package user
import (
"context"
"fmt"
"github.com/jinzhu/copier"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
)
// UpdateUser updates a user.
func (r *ResolverForUser) UpdateUser(ctx context.Context, id int, name string, pass *string, admin bool) (*gqlmodel.User, error) {
user := new(model.User)
if r.DB.Find(user, id).RecordNotFound() {
return nil, fmt.Errorf("user with id %d does not exist", id)
}
user.Name = name
user.Admin = admin
if pass != nil {
user.Pass = createPassword(*pass, r.PassStrength)
}
update := r.DB.Save(user)
gqlUser := &gqlmodel.User{}
copier.Copy(gqlUser, user)
return gqlUser, update.Error
}

77
user/update_test.go Normal file
View File

@@ -0,0 +1,77 @@
package user
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/generated/gqlmodel"
"github.com/traggo/server/model"
"github.com/traggo/server/test"
)
func TestGQL_UpdateUser_succeeds_updatesUser(t *testing.T) {
createPassword = fakePassword
db := test.InMemoryDB(t)
defer db.Close()
db.NewUserPass(1, "jmattheis", unicornPW, true)
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
user, err := resolver.UpdateUser(context.Background(), 1, "broder", pointer("pony"), false)
require.Nil(t, err)
expected := &gqlmodel.User{
Name: "broder",
ID: 1,
Admin: false,
}
require.Equal(t, expected, user)
assertUserCount(t, db, 1)
assertUserExist(t, db, model.User{
Name: "broder",
ID: 1,
Admin: false,
Pass: ponyPW,
})
}
func TestGQL_UpdateUser_succeeds_preservesPassword(t *testing.T) {
createPassword = fakePassword
db := test.InMemoryDB(t)
defer db.Close()
db.NewUserPass(1, "jmattheis", unicornPW, true)
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
user, err := resolver.UpdateUser(context.Background(), 1, "broder", nil, false)
require.Nil(t, err)
expected := &gqlmodel.User{
Name: "broder",
ID: 1,
Admin: false,
}
require.Equal(t, expected, user)
assertUserCount(t, db, 1)
assertUserExist(t, db, model.User{
Name: "broder",
ID: 1,
Admin: false,
Pass: unicornPW,
})
}
func TestGQL_UpdateUser_fails_notExistingUser(t *testing.T) {
createPassword = fakePassword
db := test.InMemoryDB(t)
defer db.Close()
resolver := ResolverForUser{DB: db.DB, PassStrength: 4}
_, err := resolver.UpdateUser(context.Background(), 1, "broder", nil, false)
require.EqualError(t, err, "user with id 1 does not exist")
assertUserCount(t, db, 0)
}
func pointer(s string) *string {
return &s
}

14
user/userresolver.go Normal file
View File

@@ -0,0 +1,14 @@
package user
import (
"github.com/jinzhu/gorm"
"github.com/traggo/server/user/password"
)
var createPassword = password.CreatePassword
// ResolverForUser resolves user specific things.
type ResolverForUser struct {
DB *gorm.DB
PassStrength int
}

36
user/utils_test.go Normal file
View File

@@ -0,0 +1,36 @@
package user
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/traggo/server/model"
"github.com/traggo/server/test"
)
var (
ponyPW = []byte{1}
unicornPW = []byte{2}
fakePassword = func(pw string, strength int) []byte {
if pw == "pony" {
return ponyPW
} else if pw == "unicorn" {
return unicornPW
}
panic("unknown pw")
}
)
func assertUserExist(t *testing.T, db *test.Database, expected model.User) {
foundUser := new(model.User)
find := db.Find(foundUser, expected.ID)
require.Nil(t, find.Error)
require.NotNil(t, foundUser)
require.Equal(t, expected, *foundUser)
}
func assertUserCount(t *testing.T, db *test.Database, expected int) {
count := new(int)
db.Model(new(model.User)).Count(count)
require.Equal(t, expected, *count)
}