snapshot of https://github.com/traggo/server.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
build / build (push) Failing after 3s
Some checks failed
build / build (push) Failing after 3s
This commit is contained in:
83
device/create.go
Normal file
83
device/create.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/traggo/server/auth"
|
||||
"github.com/traggo/server/auth/rand"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/user/password"
|
||||
)
|
||||
|
||||
var (
|
||||
timeNow = time.Now
|
||||
randToken = rand.Token
|
||||
comparePassword = password.ComparePassword
|
||||
errUserPassWrong = errors.New("username/password combination does not exist")
|
||||
)
|
||||
|
||||
// Login creates a device.
|
||||
func (r *ResolverForDevice) Login(ctx context.Context, username string, pass string, deviceName string, deviceType gqlmodel.DeviceType, cookie bool) (*gqlmodel.Login, error) {
|
||||
|
||||
user := new(model.User)
|
||||
find := r.DB.Where("name = ?", username).Find(user)
|
||||
|
||||
if find.RecordNotFound() {
|
||||
return nil, errUserPassWrong
|
||||
}
|
||||
|
||||
if !comparePassword(user.Pass, []byte(pass)) {
|
||||
return nil, errUserPassWrong
|
||||
}
|
||||
|
||||
return r.createDeviceInternal(ctx, user, deviceName, deviceType, cookie)
|
||||
}
|
||||
|
||||
// CreateDevice creates a device.
|
||||
func (r *ResolverForDevice) CreateDevice(ctx context.Context, deviceName string, deviceType gqlmodel.DeviceType) (*gqlmodel.Login, error) {
|
||||
|
||||
user := auth.GetUser(ctx)
|
||||
|
||||
return r.createDeviceInternal(ctx, user, deviceName, deviceType, false)
|
||||
}
|
||||
|
||||
func (r *ResolverForDevice) createDeviceInternal(ctx context.Context, user *model.User, deviceName string, deviceType gqlmodel.DeviceType, cookie bool) (*gqlmodel.Login, error) {
|
||||
|
||||
token := randToken(20)
|
||||
for !r.DB.Where("token = ?", token).Find(new(model.Device)).RecordNotFound() {
|
||||
token = randToken(20)
|
||||
}
|
||||
|
||||
now := timeNow()
|
||||
device := &model.Device{
|
||||
Token: token,
|
||||
UserID: user.ID,
|
||||
Name: deviceName,
|
||||
Type: model.DeviceType(deviceType),
|
||||
CreatedAt: now.UTC(),
|
||||
ActiveAt: now.UTC(),
|
||||
}
|
||||
|
||||
if err := device.Type.Valid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cookie {
|
||||
auth.GetCreateSession(ctx)(token, device.Type.Seconds())
|
||||
}
|
||||
|
||||
create := r.DB.Create(device)
|
||||
|
||||
gqlUser := &gqlmodel.User{}
|
||||
copier.Copy(gqlUser, user)
|
||||
gqlDevice := &gqlmodel.Device{}
|
||||
copier.Copy(gqlDevice, device)
|
||||
return &gqlmodel.Login{
|
||||
User: gqlUser,
|
||||
Device: gqlDevice,
|
||||
Token: token}, create.Error
|
||||
}
|
||||
271
device/create_test.go
Normal file
271
device/create_test.go
Normal file
@@ -0,0 +1,271 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/traggo/server/auth"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
)
|
||||
|
||||
var (
|
||||
existingPassword = []byte{1}
|
||||
)
|
||||
|
||||
func TestGQL_Login_fails_userDoesNotExist(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
|
||||
now := test.Time("2018-06-30T18:30:00+02:00")
|
||||
timeDispose := fakeTime(now)
|
||||
defer timeDispose()
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
login, err := resolver.Login(
|
||||
context.Background(),
|
||||
"jmattheis",
|
||||
"123",
|
||||
"test",
|
||||
gqlmodel.DeviceTypeLongExpiry,
|
||||
false)
|
||||
|
||||
assert.Nil(t, login)
|
||||
assert.Equal(t, errUserPassWrong, err)
|
||||
assertDeviceCount(t, db, 0)
|
||||
}
|
||||
|
||||
func TestGQL_Login_fails_wrongPass(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.Create(&model.User{
|
||||
Name: "jmattheis",
|
||||
ID: 1,
|
||||
Pass: existingPassword,
|
||||
})
|
||||
pwDispose := fakePassword()
|
||||
defer pwDispose()
|
||||
|
||||
now := test.Time("2018-06-30T18:30:00+02:00")
|
||||
timeDispose := fakeTime(now)
|
||||
defer timeDispose()
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
login, err := resolver.Login(
|
||||
context.Background(),
|
||||
"jmattheis",
|
||||
"123",
|
||||
"test",
|
||||
gqlmodel.DeviceTypeLongExpiry,
|
||||
false)
|
||||
|
||||
assert.Nil(t, login)
|
||||
assert.Equal(t, errUserPassWrong, err)
|
||||
assertDeviceCount(t, db, 0)
|
||||
}
|
||||
|
||||
func TestGQL_Login_succeeds(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.Create(&model.User{
|
||||
Name: "jmattheis",
|
||||
ID: 1,
|
||||
Pass: existingPassword,
|
||||
})
|
||||
pwDispose := fakePassword()
|
||||
defer pwDispose()
|
||||
|
||||
tokenDispose := fakeToken("firstToken")
|
||||
defer tokenDispose()
|
||||
|
||||
now := test.Time("2018-06-30T18:30:00+02:00")
|
||||
timeDispose := fakeTime(now)
|
||||
defer timeDispose()
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
login, err := resolver.Login(
|
||||
context.Background(),
|
||||
"jmattheis",
|
||||
"unicorn",
|
||||
"test",
|
||||
gqlmodel.DeviceTypeLongExpiry,
|
||||
false)
|
||||
|
||||
assert.Nil(t, err)
|
||||
|
||||
expected := &gqlmodel.Login{
|
||||
Token: "firstToken",
|
||||
User: &gqlmodel.User{Admin: false, ID: 1, Name: "jmattheis"},
|
||||
Device: &gqlmodel.Device{
|
||||
ID: 1,
|
||||
Name: "test",
|
||||
Type: gqlmodel.DeviceTypeLongExpiry,
|
||||
CreatedAt: model.Time(now.UTC()),
|
||||
ActiveAt: model.Time(now.UTC()),
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expected, login)
|
||||
assertDeviceCount(t, db, 1)
|
||||
}
|
||||
|
||||
func TestGQL_CreateDevice_succeeds(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
user := &model.User{
|
||||
Name: "jmattheis",
|
||||
ID: 1,
|
||||
Pass: existingPassword,
|
||||
}
|
||||
db.Create(user)
|
||||
pwDispose := fakePassword()
|
||||
defer pwDispose()
|
||||
|
||||
tokenDispose := fakeToken("firstToken")
|
||||
defer tokenDispose()
|
||||
|
||||
now := test.Time("2018-06-30T18:30:00+02:00")
|
||||
timeDispose := fakeTime(now)
|
||||
defer timeDispose()
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
login, err := resolver.CreateDevice(
|
||||
auth.WithUser(context.Background(), user),
|
||||
"test",
|
||||
gqlmodel.DeviceTypeLongExpiry)
|
||||
|
||||
assert.Nil(t, err)
|
||||
|
||||
expected := &gqlmodel.Login{
|
||||
Token: "firstToken",
|
||||
User: &gqlmodel.User{Admin: false, ID: 1, Name: "jmattheis"},
|
||||
Device: &gqlmodel.Device{
|
||||
ID: 1,
|
||||
Name: "test",
|
||||
Type: gqlmodel.DeviceTypeLongExpiry,
|
||||
CreatedAt: model.Time(now.UTC()),
|
||||
ActiveAt: model.Time(now.UTC()),
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expected, login)
|
||||
assertDeviceCount(t, db, 1)
|
||||
}
|
||||
|
||||
func TestGQL_Login_setsCookie(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.Create(&model.User{
|
||||
Name: "jmattheis",
|
||||
ID: 1,
|
||||
Pass: existingPassword,
|
||||
})
|
||||
pwDispose := fakePassword()
|
||||
defer pwDispose()
|
||||
|
||||
tokenDispose := fakeToken("firstToken")
|
||||
defer tokenDispose()
|
||||
|
||||
now := test.Time("2018-06-30T18:30:00+02:00")
|
||||
timeDispose := fakeTime(now)
|
||||
defer timeDispose()
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
|
||||
createSessionToken := ""
|
||||
createSessionAge := 0
|
||||
|
||||
_, err := resolver.Login(
|
||||
auth.WithCreateSession(context.Background(), func(token string, age int) {
|
||||
createSessionToken = token
|
||||
createSessionAge = age
|
||||
}),
|
||||
"jmattheis",
|
||||
"unicorn",
|
||||
"test",
|
||||
gqlmodel.DeviceTypeShortExpiry,
|
||||
true)
|
||||
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "firstToken", createSessionToken)
|
||||
assert.Equal(t, 60*60, createSessionAge)
|
||||
assertDeviceCount(t, db, 1)
|
||||
}
|
||||
|
||||
func TestGQL_Login_succeeds_withExistingToken(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.Create(&model.User{
|
||||
Name: "jmattheis",
|
||||
ID: 1,
|
||||
Pass: existingPassword,
|
||||
})
|
||||
db.Create(&model.Device{
|
||||
Name: "test",
|
||||
ID: 1,
|
||||
Token: "firstToken",
|
||||
UserID: 1,
|
||||
})
|
||||
pwDispose := fakePassword()
|
||||
defer pwDispose()
|
||||
|
||||
tokenDispose := fakeToken("firstToken", "secondToken")
|
||||
defer tokenDispose()
|
||||
|
||||
now := test.Time("2018-06-30T18:30:00+02:00")
|
||||
timeDispose := fakeTime(now)
|
||||
defer timeDispose()
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
login, err := resolver.Login(
|
||||
context.Background(),
|
||||
"jmattheis",
|
||||
"unicorn",
|
||||
"test",
|
||||
gqlmodel.DeviceTypeShortExpiry,
|
||||
false)
|
||||
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "secondToken", login.Token)
|
||||
assertDeviceCount(t, db, 2)
|
||||
}
|
||||
|
||||
func fakePassword() func() {
|
||||
old := comparePassword
|
||||
comparePassword = func(hashedPassword, password []byte) bool {
|
||||
return bytes.Equal(password, []byte("unicorn")) && bytes.Equal(hashedPassword, existingPassword)
|
||||
}
|
||||
return func() {
|
||||
comparePassword = old
|
||||
}
|
||||
}
|
||||
|
||||
func fakeTime(t time.Time) func() {
|
||||
old := timeNow
|
||||
timeNow = func() time.Time {
|
||||
return t
|
||||
}
|
||||
return func() {
|
||||
timeNow = old
|
||||
}
|
||||
}
|
||||
|
||||
func fakeToken(token ...string) func() {
|
||||
old := randToken
|
||||
remaining := token
|
||||
randToken = func(n int) string {
|
||||
if len(remaining) > 0 {
|
||||
used := remaining[0]
|
||||
remaining = remaining[1:]
|
||||
return used
|
||||
}
|
||||
panic("oops no token specified")
|
||||
}
|
||||
return func() {
|
||||
randToken = old
|
||||
}
|
||||
}
|
||||
20
device/current.go
Normal file
20
device/current.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/traggo/server/auth"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
)
|
||||
|
||||
// CurrentDevice returns the current device.
|
||||
func (r *ResolverForDevice) CurrentDevice(ctx context.Context) (*gqlmodel.Device, error) {
|
||||
device := auth.GetDevice(ctx)
|
||||
if device == nil {
|
||||
return nil, nil
|
||||
}
|
||||
var result gqlmodel.Device
|
||||
copier.Copy(&result, device)
|
||||
return &result, nil
|
||||
}
|
||||
53
device/current_test.go
Normal file
53
device/current_test.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
"github.com/traggo/server/test/fake"
|
||||
)
|
||||
|
||||
func TestGQL_CurrentDevice_withDevice(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
|
||||
device := &model.Device{
|
||||
ID: 2,
|
||||
Name: "Browser",
|
||||
Token: "abcd",
|
||||
UserID: 2,
|
||||
CreatedAt: test.Time("2004-06-30T18:30:00Z"),
|
||||
ActiveAt: test.Time("2015-06-30T18:30:00Z"),
|
||||
Type: model.TypeNoExpiry,
|
||||
}
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
result, err := resolver.CurrentDevice(fake.Device(device))
|
||||
|
||||
require.Nil(t, err)
|
||||
expected := &gqlmodel.Device{
|
||||
ID: 2,
|
||||
Name: "Browser",
|
||||
CreatedAt: test.ModelTimeUTC("2004-06-30T18:30:00Z"),
|
||||
ActiveAt: test.ModelTimeUTC("2015-06-30T18:30:00Z"),
|
||||
Type: gqlmodel.DeviceTypeNoExpiry,
|
||||
}
|
||||
|
||||
require.Equal(t, expected, result)
|
||||
}
|
||||
|
||||
func TestGQL_CurrentDevice_noDevice(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
result, err := resolver.CurrentDevice(context.Background())
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Nil(t, result)
|
||||
}
|
||||
8
device/deviceresolver.go
Normal file
8
device/deviceresolver.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package device
|
||||
|
||||
import "github.com/jinzhu/gorm"
|
||||
|
||||
// ResolverForDevice resolves device specific things.
|
||||
type ResolverForDevice struct {
|
||||
DB *gorm.DB
|
||||
}
|
||||
20
device/get.go
Normal file
20
device/get.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/traggo/server/auth"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
)
|
||||
|
||||
// Devices returns all devices.
|
||||
func (r *ResolverForDevice) Devices(ctx context.Context) ([]*gqlmodel.Device, error) {
|
||||
user := auth.GetUser(ctx)
|
||||
var devices []model.Device
|
||||
find := r.DB.Where(&model.Device{UserID: user.ID}).Order("active_at DESC").Find(&devices)
|
||||
var result []*gqlmodel.Device
|
||||
copier.Copy(&result, &devices)
|
||||
return result, find.Error
|
||||
}
|
||||
51
device/get_test.go
Normal file
51
device/get_test.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
"github.com/traggo/server/test/fake"
|
||||
)
|
||||
|
||||
func TestGQL_Devices(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.User(1)
|
||||
db.User(2)
|
||||
db.Create(&model.Device{
|
||||
ID: 1,
|
||||
Name: "Android",
|
||||
Token: "abc",
|
||||
UserID: 1,
|
||||
CreatedAt: test.Time("2009-06-30T18:30:00Z"),
|
||||
ActiveAt: test.Time("2018-06-30T18:30:00Z"),
|
||||
Type: model.TypeNoExpiry,
|
||||
})
|
||||
db.Create(&model.Device{
|
||||
ID: 2,
|
||||
Name: "Browser",
|
||||
Token: "abcd",
|
||||
UserID: 2,
|
||||
CreatedAt: test.Time("2004-06-30T18:30:00Z"),
|
||||
ActiveAt: test.Time("2015-06-30T18:30:00Z"),
|
||||
Type: model.TypeNoExpiry,
|
||||
})
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
devices, err := resolver.Devices(fake.User(1))
|
||||
|
||||
require.Nil(t, err)
|
||||
expected := []*gqlmodel.Device{
|
||||
{
|
||||
ID: 1,
|
||||
Name: "Android",
|
||||
CreatedAt: test.ModelTimeUTC("2009-06-30T18:30:00Z"),
|
||||
ActiveAt: test.ModelTimeUTC("2018-06-30T18:30:00Z"),
|
||||
Type: gqlmodel.DeviceTypeNoExpiry,
|
||||
},
|
||||
}
|
||||
require.Equal(t, expected, devices)
|
||||
}
|
||||
24
device/remove.go
Normal file
24
device/remove.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/traggo/server/auth"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
)
|
||||
|
||||
// RemoveDevice removes a device
|
||||
func (r *ResolverForDevice) RemoveDevice(ctx context.Context, id int) (*gqlmodel.Device, error) {
|
||||
device := model.Device{ID: id}
|
||||
if r.DB.Where(&model.Device{UserID: auth.GetUser(ctx).ID}).Find(&device).RecordNotFound() {
|
||||
return nil, fmt.Errorf("device not found")
|
||||
}
|
||||
|
||||
remove := r.DB.Delete(&device)
|
||||
gqlDevice := &gqlmodel.Device{}
|
||||
copier.Copy(gqlDevice, &device)
|
||||
return gqlDevice, remove.Error
|
||||
}
|
||||
18
device/remove_current.go
Normal file
18
device/remove_current.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/traggo/server/auth"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
)
|
||||
|
||||
// RemoveCurrentDevice removes the current authenticated device
|
||||
func (r *ResolverForDevice) RemoveCurrentDevice(ctx context.Context) (*gqlmodel.Device, error) {
|
||||
device := auth.GetDevice(ctx)
|
||||
remove := r.DB.Delete(device)
|
||||
gqlDevice := &gqlmodel.Device{}
|
||||
copier.Copy(gqlDevice, device)
|
||||
return gqlDevice, remove.Error
|
||||
}
|
||||
41
device/remove_current_test.go
Normal file
41
device/remove_current_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
"github.com/traggo/server/test/fake"
|
||||
)
|
||||
|
||||
func TestGQL_RemoveCurrentDevice_succeeds_removesDevice(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.User(1)
|
||||
device := &model.Device{
|
||||
ID: 55,
|
||||
Name: "Android",
|
||||
Token: "abc",
|
||||
UserID: 1,
|
||||
CreatedAt: test.Time("2009-06-30T18:30:00Z"),
|
||||
ActiveAt: test.Time("2018-06-30T18:30:00Z"),
|
||||
Type: model.TypeNoExpiry,
|
||||
}
|
||||
db.Create(device)
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
gqlDevice, err := resolver.RemoveCurrentDevice(fake.Device(device))
|
||||
require.Nil(t, err)
|
||||
|
||||
expected := &gqlmodel.Device{
|
||||
ID: 55,
|
||||
Name: "Android",
|
||||
CreatedAt: test.ModelTimeUTC("2009-06-30T18:30:00Z"),
|
||||
ActiveAt: test.ModelTimeUTC("2018-06-30T18:30:00Z"),
|
||||
Type: gqlmodel.DeviceTypeNoExpiry,
|
||||
}
|
||||
|
||||
require.Equal(t, expected, gqlDevice)
|
||||
assertDeviceCount(t, db, 0)
|
||||
}
|
||||
58
device/remove_test.go
Normal file
58
device/remove_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
"github.com/traggo/server/test/fake"
|
||||
)
|
||||
|
||||
func TestGQL_RemoveDevice_succeeds_removesDevice(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.User(1)
|
||||
db.Create(&model.Device{
|
||||
ID: 55,
|
||||
Name: "Android",
|
||||
Token: "abc",
|
||||
UserID: 1,
|
||||
CreatedAt: test.Time("2009-06-30T18:30:00+02:00"),
|
||||
ActiveAt: test.Time("2018-06-30T18:30:00+02:00"),
|
||||
Type: model.TypeNoExpiry,
|
||||
})
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
_, err := resolver.RemoveDevice(fake.User(1), 55)
|
||||
require.Nil(t, err)
|
||||
assertDeviceCount(t, db, 0)
|
||||
}
|
||||
|
||||
func TestGQL_RemoveDevice_fails_notExistingDevice(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.User(1)
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
_, err := resolver.RemoveDevice(fake.User(1), 55)
|
||||
require.EqualError(t, err, "device not found")
|
||||
}
|
||||
|
||||
func TestGQL_RemoveDevice_fails_notPermission(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.User(1)
|
||||
db.User(2)
|
||||
db.Create(&model.Device{
|
||||
ID: 55,
|
||||
Name: "Android",
|
||||
Token: "abc",
|
||||
UserID: 2,
|
||||
CreatedAt: test.Time("2009-06-30T18:30:00+02:00"),
|
||||
ActiveAt: test.Time("2018-06-30T18:30:00+02:00"),
|
||||
Type: model.TypeNoExpiry,
|
||||
})
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
_, err := resolver.RemoveDevice(fake.User(1), 55)
|
||||
require.EqualError(t, err, "device not found")
|
||||
}
|
||||
29
device/update.go
Normal file
29
device/update.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/jinzhu/copier"
|
||||
"github.com/traggo/server/auth"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
)
|
||||
|
||||
// UpdateDevice updates a device.
|
||||
func (r *ResolverForDevice) UpdateDevice(ctx context.Context, id int, name string, deviceType gqlmodel.DeviceType) (*gqlmodel.Device, error) {
|
||||
device := new(model.Device)
|
||||
if r.DB.Where("user_id = ?", auth.GetUser(ctx).ID).Find(device, id).RecordNotFound() {
|
||||
return nil, errors.New("device not found")
|
||||
}
|
||||
|
||||
device.Name = name
|
||||
device.Type = model.DeviceType(deviceType)
|
||||
if err := device.Type.Valid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
update := r.DB.Save(device)
|
||||
gqlDevice := &gqlmodel.Device{}
|
||||
copier.Copy(gqlDevice, device)
|
||||
return gqlDevice, update.Error
|
||||
}
|
||||
94
device/update_test.go
Normal file
94
device/update_test.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/traggo/server/generated/gqlmodel"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
"github.com/traggo/server/test/fake"
|
||||
)
|
||||
|
||||
func TestGQL_UpdateDevice_succeeds_updatesDevice(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.Create(&model.User{
|
||||
Name: "jmattheis",
|
||||
ID: 1,
|
||||
Admin: true,
|
||||
})
|
||||
db.Create(&model.Device{
|
||||
Name: "old name",
|
||||
ID: 1,
|
||||
UserID: 1,
|
||||
CreatedAt: test.Time("2009-06-30T18:30:00Z"),
|
||||
ActiveAt: test.Time("2018-06-30T18:30:00Z"),
|
||||
Type: model.TypeNoExpiry,
|
||||
})
|
||||
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
device, err := resolver.UpdateDevice(fake.User(1), 1, "updated name", gqlmodel.DeviceTypeShortExpiry)
|
||||
require.Nil(t, err)
|
||||
|
||||
expected := &gqlmodel.Device{
|
||||
Name: "updated name",
|
||||
ID: 1,
|
||||
CreatedAt: test.ModelTimeUTC("2009-06-30T18:30:00Z"),
|
||||
ActiveAt: test.ModelTimeUTC("2018-06-30T18:30:00Z"),
|
||||
Type: gqlmodel.DeviceTypeShortExpiry,
|
||||
}
|
||||
require.Equal(t, expected, device)
|
||||
assertDeviceCount(t, db, 1)
|
||||
assertDeviceExist(t, db, model.Device{
|
||||
Name: "updated name",
|
||||
ID: 1,
|
||||
UserID: 1,
|
||||
CreatedAt: test.Time("2009-06-30T18:30:00Z"),
|
||||
ActiveAt: test.Time("2018-06-30T18:30:00Z"),
|
||||
Type: model.TypeShortExpiry,
|
||||
})
|
||||
}
|
||||
|
||||
func TestGQL_UpdateDevice_fails_notExistingDevice(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.Create(&model.User{
|
||||
Name: "jmattheis",
|
||||
ID: 1,
|
||||
Admin: true,
|
||||
})
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
_, err := resolver.UpdateDevice(fake.User(1), 3, "tst", gqlmodel.DeviceTypeShortExpiry)
|
||||
require.EqualError(t, err, "device not found")
|
||||
|
||||
assertDeviceCount(t, db, 0)
|
||||
}
|
||||
|
||||
func TestGQL_UpdateDevice_fails_noPermissions(t *testing.T) {
|
||||
db := test.InMemoryDB(t)
|
||||
defer db.Close()
|
||||
db.Create(&model.User{
|
||||
Name: "jmattheis",
|
||||
ID: 1,
|
||||
Admin: true,
|
||||
})
|
||||
db.Create(&model.User{
|
||||
Name: "broderp",
|
||||
ID: 2,
|
||||
Admin: true,
|
||||
})
|
||||
db.Create(&model.Device{
|
||||
Name: "old name",
|
||||
ID: 66,
|
||||
UserID: 2,
|
||||
CreatedAt: test.Time("2009-06-30T18:30:00Z"),
|
||||
ActiveAt: test.Time("2018-06-30T18:30:00Z"),
|
||||
Type: model.TypeNoExpiry,
|
||||
})
|
||||
resolver := ResolverForDevice{DB: db.DB}
|
||||
_, err := resolver.UpdateDevice(fake.User(1), 66, "tst", gqlmodel.DeviceTypeNoExpiry)
|
||||
require.EqualError(t, err, "device not found")
|
||||
|
||||
assertDeviceCount(t, db, 1)
|
||||
}
|
||||
23
device/utils_test.go
Normal file
23
device/utils_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package device
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/traggo/server/model"
|
||||
"github.com/traggo/server/test"
|
||||
)
|
||||
|
||||
func assertDeviceExist(t *testing.T, db *test.Database, expected model.Device) {
|
||||
foundDevice := new(model.Device)
|
||||
find := db.Find(foundDevice, expected.ID)
|
||||
require.Nil(t, find.Error)
|
||||
require.NotNil(t, foundDevice)
|
||||
require.Equal(t, expected, *foundDevice)
|
||||
}
|
||||
|
||||
func assertDeviceCount(t *testing.T, db *test.Database, expected int) {
|
||||
count := new(int)
|
||||
db.Model(new(model.Device)).Count(count)
|
||||
require.Equal(t, expected, *count)
|
||||
}
|
||||
Reference in New Issue
Block a user