Refactor User and DB handling #123
|
@ -16,7 +16,12 @@ In general, this api repo has the following structure:
|
|||
* `docs`
|
||||
* `pkg`
|
||||
* `caldav`
|
||||
* `cmd`
|
||||
* `config`
|
||||
* `db`
|
||||
* `fixtures`
|
||||
* `files`
|
||||
* `integration`
|
||||
* `log`
|
||||
* `mail`
|
||||
* `metrics`
|
||||
|
@ -29,8 +34,11 @@ In general, this api repo has the following structure:
|
|||
* `red`
|
||||
* `routes`
|
||||
* `api/v1`
|
||||
* `static`
|
||||
* `swagger`
|
||||
* `user`
|
||||
* `utils`
|
||||
* `version`
|
||||
* `REST-Tests`
|
||||
* `templates`
|
||||
* `vendor`
|
||||
|
@ -70,6 +78,21 @@ how to interpret which env variables for config etc.
|
|||
|
||||
If you want to add a new config parameter, you should add default value in this package.
|
||||
|
||||
### db
|
||||
|
||||
This package contains the db connection handling and db fixtures for testing.
|
||||
Each other package gets its db connection object from this package.
|
||||
|
||||
### files
|
||||
|
||||
This package is responsible for all file-related things.
|
||||
This means it handles saving and retrieving files from the db and the underlying file system.
|
||||
|
||||
### integration
|
||||
|
||||
All integration tests live here.
|
||||
See [integration tests]({{< ref "test.md" >}}#integration-tests) for more details.
|
||||
|
||||
### log
|
||||
|
||||
Similar to `config`, this will set up the logging, based on differen logging backends.
|
||||
|
@ -127,11 +150,19 @@ To add a new route, see [adding a new route]({{< ref "../practical-instructions/
|
|||
This is where all http-handler functions for the api are stored.
|
||||
Every handler function which does not use the standard web handler should live here.
|
||||
|
||||
### static
|
||||
|
||||
All static files generated by `make generate` live here.
|
||||
|
||||
### swagger
|
||||
|
||||
This is where the [generated]({{< ref "make.md#generate-swagger-definitions-from-code-comments">}} [api docs]({{< ref "../usage/api.md">}}) live.
|
||||
You usually don't need to touch this package.
|
||||
|
||||
### user
|
||||
|
||||
All user-related things like registration etc. live in this package.
|
||||
|
||||
### utils
|
||||
|
||||
A small package, containing some helper functions:
|
||||
|
@ -141,6 +172,12 @@ A small package, containing some helper functions:
|
|||
|
||||
See their function definitions for instructions on how to use them.
|
||||
|
||||
### version
|
||||
|
||||
The single purpouse of this package is to hold the current vikunja version which gets overridden through build flags
|
||||
each time `make release` or `make build` is run.
|
||||
It is a seperate package to avoid import cycles with other packages.
|
||||
|
||||
## REST-Tests
|
||||
|
||||
Holds all kinds of test files to directly test the api from inside of [jetbrains ide's](https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html).
|
||||
|
|
|
@ -42,3 +42,29 @@ The integration tests use the same config and fixtures as the unit tests and the
|
|||
see at the beginning of this document.
|
||||
|
||||
To run integration tests, use `make integration-test`.
|
||||
|
||||
# Initializing db fixtures when writing tests
|
||||
|
||||
All db fixtures for all tests live in the `pkg/db/fixtures/` folder as yaml files.
|
||||
Each file has the same name as the table the fixtures are for.
|
||||
You should put new fixtures in this folder.
|
||||
|
||||
When initializing db fixtures, you are responsible for defining which tables your package needs in your test init function.
|
||||
Usually, this is done as follows (this code snippet is taken from the `user` package):
|
||||
|
||||
```go
|
||||
err = db.InitTestFixtures("users")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
In your actual tests, you then load the fixtures into the in-memory db like so:
|
||||
|
||||
```go
|
||||
db.LoadAndAssertFixtures(t)
|
||||
```
|
||||
|
||||
This will load all fixtures you defined in your test init method.
|
||||
You should always use this method to load fixtures, the only exception is when your package tests require extra test
|
||||
fixtures other than db fixtures (like files).
|
||||
|
|
1
go.mod
1
go.mod
|
@ -59,7 +59,6 @@ require (
|
|||
github.com/onsi/gomega v1.4.3 // indirect
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||
github.com/pelletier/go-toml v1.4.0 // indirect
|
||||
github.com/pkg/errors v0.8.1 // indirect
|
||||
github.com/prometheus/client_golang v0.9.2
|
||||
github.com/samedi/caldav-go v3.0.0+incompatible
|
||||
github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package caldav
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
@ -49,7 +49,7 @@ type Todo struct {
|
|||
Summary string
|
||||
Description string
|
||||
CompletedUnix int64
|
||||
Organizer *models.User
|
||||
Organizer *user.User
|
||||
Priority int64 // 0-9, 1 is highest
|
||||
RelatedToUID string
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"code.vikunja.io/api/pkg/models"
|
||||
migrator "code.vikunja.io/api/pkg/modules/migration"
|
||||
"code.vikunja.io/api/pkg/red"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
|
@ -76,6 +77,10 @@ func initialize() {
|
|||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
err = user.InitDB()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
err = files.SetEngine()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
|
|
28
pkg/db/db.go
28
pkg/db/db.go
|
@ -23,7 +23,6 @@ import (
|
|||
"fmt"
|
||||
"github.com/go-xorm/core"
|
||||
"github.com/go-xorm/xorm"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
|
@ -85,33 +84,6 @@ func CreateDBEngine() (engine *xorm.Engine, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// CreateTestEngine creates an instance of the db engine which lives in memory
|
||||
func CreateTestEngine() (engine *xorm.Engine, err error) {
|
||||
|
||||
if x != nil {
|
||||
return x, nil
|
||||
}
|
||||
|
||||
if os.Getenv("VIKUNJA_TESTS_USE_CONFIG") == "1" {
|
||||
config.InitConfig()
|
||||
engine, err = CreateDBEngine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
engine, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
engine.SetMapper(core.GonicMapper{})
|
||||
engine.ShowSQL(os.Getenv("UNIT_TESTS_VERBOSE") == "1")
|
||||
engine.SetLogger(xorm.NewSimpleLogger(log.GetLogWriter("database")))
|
||||
x = engine
|
||||
return
|
||||
}
|
||||
|
||||
// RegisterTableStructsForCache registers tables in gob encoding for redis cache
|
||||
func RegisterTableStructsForCache(val interface{}) {
|
||||
gob.Register(val)
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
// Copyright2018-2020 Vikunja and contriubtors. All rights reserved.
|
||||
//
|
||||
// This file is part of Vikunja.
|
||||
//
|
||||
// Vikunja is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vikunja is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"github.com/go-xorm/core"
|
||||
"github.com/go-xorm/xorm"
|
||||
"os"
|
||||
)
|
||||
|
||||
// CreateTestEngine creates an instance of the db engine which lives in memory
|
||||
func CreateTestEngine() (engine *xorm.Engine, err error) {
|
||||
|
||||
if x != nil {
|
||||
return x, nil
|
||||
}
|
||||
|
||||
if os.Getenv("VIKUNJA_TESTS_USE_CONFIG") == "1" {
|
||||
config.InitConfig()
|
||||
engine, err = CreateDBEngine()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
engine, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
engine.SetMapper(core.GonicMapper{})
|
||||
engine.ShowSQL(os.Getenv("UNIT_TESTS_VERBOSE") == "1")
|
||||
engine.SetLogger(xorm.NewSimpleLogger(log.GetLogWriter("database")))
|
||||
x = engine
|
||||
return
|
||||
}
|
||||
|
||||
// InitTestFixtures populates the db with all fixtures from the fixtures folder
|
||||
func InitTestFixtures(tablenames ...string) (err error) {
|
||||
// Create all fixtures
|
||||
config.InitDefaultConfig()
|
||||
// We need to set the root path even if we're not using the config, otherwise fixtures are not loaded correctly
|
||||
config.ServiceRootpath.Set(os.Getenv("VIKUNJA_SERVICE_ROOTPATH"))
|
||||
|
||||
// Sync fixtures
|
||||
err = InitFixtures(tablenames...)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -18,15 +18,36 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/testfixtures.v2"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var fixtures *testfixtures.Context
|
||||
|
||||
// InitFixtures initialize test fixtures for a test database
|
||||
func InitFixtures(helper testfixtures.Helper, dir string) (err error) {
|
||||
func InitFixtures(tablenames ...string) (err error) {
|
||||
|
||||
var helper testfixtures.Helper = &testfixtures.SQLite{}
|
||||
if config.DatabaseType.GetString() == "mysql" {
|
||||
helper = &testfixtures.MySQL{}
|
||||
}
|
||||
dir := filepath.Join(config.ServiceRootpath.GetString(), "pkg", "db", "fixtures")
|
||||
|
||||
testfixtures.SkipDatabaseNameCheck(true)
|
||||
fixtures, err = testfixtures.NewFolder(x.DB().DB, helper, dir)
|
||||
|
||||
// If fixture table names are specified, load them
|
||||
// Otherwise, load all fixtures
|
||||
if len(tablenames) > 0 {
|
||||
for i, name := range tablenames {
|
||||
tablenames[i] = filepath.Join(dir, name+".yml")
|
||||
}
|
||||
fixtures, err = testfixtures.NewFiles(x.DB().DB, helper, tablenames...)
|
||||
} else {
|
||||
fixtures, err = testfixtures.NewFolder(x.DB().DB, helper, dir)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -34,3 +55,9 @@ func InitFixtures(helper testfixtures.Helper, dir string) (err error) {
|
|||
func LoadFixtures() error {
|
||||
return fixtures.Load()
|
||||
}
|
||||
|
||||
// LoadAndAssertFixtures loads all fixtures defined before and asserts they are correctly loaded
|
||||
func LoadAndAssertFixtures(t *testing.T) {
|
||||
err := LoadFixtures()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
|
|
@ -22,9 +22,7 @@ import (
|
|||
"code.vikunja.io/api/pkg/log"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/testfixtures.v2"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -45,10 +43,9 @@ func InitTestFileHandler() {
|
|||
}
|
||||
|
||||
func initFixtures(t *testing.T) {
|
||||
// Init db fixtures
|
||||
err := db.LoadFixtures()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// DB fixtures
|
||||
db.LoadAndAssertFixtures(t)
|
||||
// File fixtures
|
||||
InitTestFileFixtures(t)
|
||||
}
|
||||
|
||||
|
@ -73,17 +70,7 @@ func InitTests() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
config.InitDefaultConfig()
|
||||
// We need to set the root path even if we're not using the config, otherwise fixtures are not loaded correctly
|
||||
config.ServiceRootpath.Set(os.Getenv("VIKUNJA_SERVICE_ROOTPATH"))
|
||||
|
||||
// Sync fixtures
|
||||
var fixturesHelper testfixtures.Helper = &testfixtures.SQLite{}
|
||||
if config.DatabaseType.GetString() == "mysql" {
|
||||
fixturesHelper = &testfixtures.MySQL{}
|
||||
}
|
||||
fixturesDir := filepath.Join(config.ServiceRootpath.GetString(), "pkg", "files", "fixtures")
|
||||
err = db.InitFixtures(fixturesHelper, fixturesDir)
|
||||
err = db.InitTestFixtures("files")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/routes"
|
||||
v1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
|
@ -38,34 +39,34 @@ import (
|
|||
|
||||
// These are the test users, the same way they are in the test database
|
||||
var (
|
||||
testuser1 = models.User{
|
||||
testuser1 = user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
Email: "user1@example.com",
|
||||
IsActive: true,
|
||||
}
|
||||
testuser2 = models.User{
|
||||
testuser2 = user.User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
Email: "user2@example.com",
|
||||
}
|
||||
testuser3 = models.User{
|
||||
testuser3 = user.User{
|
||||
ID: 3,
|
||||
Username: "user3",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
Email: "user3@example.com",
|
||||
PasswordResetToken: "passwordresettesttoken",
|
||||
}
|
||||
testuser4 = models.User{
|
||||
testuser4 = user.User{
|
||||
ID: 4,
|
||||
Username: "user4",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
Email: "user4@example.com",
|
||||
EmailConfirmToken: "tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael",
|
||||
}
|
||||
testuser5 = models.User{
|
||||
testuser5 = user.User{
|
||||
ID: 4,
|
||||
Username: "user5",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -81,7 +82,8 @@ func setupTestEnv() (e *echo.Echo, err error) {
|
|||
config.ServiceRootpath.Set(os.Getenv("VIKUNJA_SERVICE_ROOTPATH"))
|
||||
// Some tests use the file engine, so we'll need to initialize that
|
||||
files.InitTests()
|
||||
models.SetupTests(config.ServiceRootpath.GetString())
|
||||
user.InitTests()
|
||||
models.SetupTests()
|
||||
|
||||
err = db.LoadFixtures()
|
||||
if err != nil {
|
||||
|
@ -114,7 +116,7 @@ func newTestRequest(t *testing.T, method string, handler func(ctx echo.Context)
|
|||
return
|
||||
}
|
||||
|
||||
func addUserTokenToContext(t *testing.T, user *models.User, c echo.Context) {
|
||||
func addUserTokenToContext(t *testing.T, user *user.User, c echo.Context) {
|
||||
// Get the token as a string
|
||||
token, err := v1.NewUserJWTAuthtoken(user)
|
||||
assert.NoError(t, err)
|
||||
|
@ -152,7 +154,7 @@ func testRequestSetup(t *testing.T, method string, payload string, queryParams u
|
|||
return
|
||||
}
|
||||
|
||||
func newTestRequestWithUser(t *testing.T, method string, handler echo.HandlerFunc, user *models.User, payload string, queryParams url.Values, urlParams map[string]string) (rec *httptest.ResponseRecorder, err error) {
|
||||
func newTestRequestWithUser(t *testing.T, method string, handler echo.HandlerFunc, user *user.User, payload string, queryParams url.Values, urlParams map[string]string) (rec *httptest.ResponseRecorder, err error) {
|
||||
rec, c := testRequestSetup(t, method, payload, queryParams, urlParams)
|
||||
addUserTokenToContext(t, user, c)
|
||||
err = handler(c)
|
||||
|
@ -185,7 +187,7 @@ func assertHandlerErrorCode(t *testing.T, err error, expectedErrorCode int) {
|
|||
}
|
||||
|
||||
type webHandlerTest struct {
|
||||
user *models.User
|
||||
user *user.User
|
||||
linkShare *models.LinkSharing
|
||||
strFunc func() handler.CObject
|
||||
t *testing.T
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package integrations
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
@ -36,7 +36,7 @@ func TestLogin(t *testing.T) {
|
|||
t.Run("Empty payload", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeNoUsernamePassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
|
||||
})
|
||||
t.Run("Not existing user", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{
|
||||
|
@ -44,7 +44,7 @@ func TestLogin(t *testing.T) {
|
|||
"password": "1234"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeWrongUsernameOrPassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeWrongUsernameOrPassword)
|
||||
})
|
||||
t.Run("Wrong password", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{
|
||||
|
@ -52,7 +52,7 @@ func TestLogin(t *testing.T) {
|
|||
"password": "wrong"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeWrongUsernameOrPassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeWrongUsernameOrPassword)
|
||||
})
|
||||
t.Run("user with unconfirmed email", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{
|
||||
|
@ -60,6 +60,6 @@ func TestLogin(t *testing.T) {
|
|||
"password": "1234"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeEmailNotConfirmed)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeEmailNotConfirmed)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package integrations
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
@ -37,7 +37,7 @@ func TestRegister(t *testing.T) {
|
|||
t.Run("Empty payload", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.RegisterUser, `{}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeNoUsernamePassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
|
||||
})
|
||||
t.Run("Empty username", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.RegisterUser, `{
|
||||
|
@ -46,7 +46,7 @@ func TestRegister(t *testing.T) {
|
|||
"email": "email@example.com"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeNoUsernamePassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
|
||||
})
|
||||
t.Run("Empty password", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.RegisterUser, `{
|
||||
|
@ -55,7 +55,7 @@ func TestRegister(t *testing.T) {
|
|||
"email": "email@example.com"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeNoUsernamePassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
|
||||
})
|
||||
t.Run("Empty email", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.RegisterUser, `{
|
||||
|
@ -64,7 +64,7 @@ func TestRegister(t *testing.T) {
|
|||
"email": ""
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeNoUsernamePassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
|
||||
})
|
||||
t.Run("Already existing username", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.RegisterUser, `{
|
||||
|
@ -73,7 +73,7 @@ func TestRegister(t *testing.T) {
|
|||
"email": "email@example.com"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrorCodeUsernameExists)
|
||||
assertHandlerErrorCode(t, err, user.ErrorCodeUsernameExists)
|
||||
})
|
||||
t.Run("Already existing email", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.RegisterUser, `{
|
||||
|
@ -82,6 +82,6 @@ func TestRegister(t *testing.T) {
|
|||
"email": "user1@example.com"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrorCodeUserEmailExists)
|
||||
assertHandlerErrorCode(t, err, user.ErrorCodeUserEmailExists)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package integrations
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
@ -39,7 +39,7 @@ func TestUserChangePassword(t *testing.T) {
|
|||
"old_password": "invalid"
|
||||
}`, nil, nil)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeWrongUsernameOrPassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeWrongUsernameOrPassword)
|
||||
})
|
||||
t.Run("Empty old password", func(t *testing.T) {
|
||||
_, err := newTestRequestWithUser(t, http.MethodPost, apiv1.UserChangePassword, &testuser1, `{
|
||||
|
@ -47,7 +47,7 @@ func TestUserChangePassword(t *testing.T) {
|
|||
"old_password": ""
|
||||
}`, nil, nil)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeEmptyOldPassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeEmptyOldPassword)
|
||||
})
|
||||
t.Run("Empty new password", func(t *testing.T) {
|
||||
_, err := newTestRequestWithUser(t, http.MethodPost, apiv1.UserChangePassword, &testuser1, `{
|
||||
|
@ -55,6 +55,6 @@ func TestUserChangePassword(t *testing.T) {
|
|||
"old_password": "1234"
|
||||
}`, nil, nil)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeEmptyNewPassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeEmptyNewPassword)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package integrations
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
|
@ -35,16 +35,16 @@ func TestUserConfirmEmail(t *testing.T) {
|
|||
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{}`)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, http.StatusPreconditionFailed, err.(*echo.HTTPError).Code)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeInvalidEmailConfirmToken)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeInvalidEmailConfirmToken)
|
||||
})
|
||||
t.Run("Empty token", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{"token": ""}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeInvalidEmailConfirmToken)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeInvalidEmailConfirmToken)
|
||||
})
|
||||
t.Run("Invalid token", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{"token": "invalidToken"}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeInvalidEmailConfirmToken)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeInvalidEmailConfirmToken)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package integrations
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
|
@ -34,7 +34,7 @@ func TestUserRequestResetPasswordToken(t *testing.T) {
|
|||
t.Run("Empty payload", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeNoUsernamePassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
|
||||
})
|
||||
t.Run("Invalid email address", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{"email": "user1example.com"}`)
|
||||
|
@ -44,6 +44,6 @@ func TestUserRequestResetPasswordToken(t *testing.T) {
|
|||
t.Run("No user with that email address", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{"email": "user1000@example.com"}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeUserDoesNotExist)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeUserDoesNotExist)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
package integrations
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
|
@ -45,7 +45,7 @@ func TestUserPasswordReset(t *testing.T) {
|
|||
"token": "passwordresettesttoken"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeNoUsernamePassword)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
|
||||
})
|
||||
t.Run("Invalid password reset token", func(t *testing.T) {
|
||||
_, err := newTestRequest(t, http.MethodPost, apiv1.UserResetPassword, `{
|
||||
|
@ -53,6 +53,6 @@ func TestUserPasswordReset(t *testing.T) {
|
|||
"token": "invalidtoken"
|
||||
}`)
|
||||
assert.Error(t, err)
|
||||
assertHandlerErrorCode(t, err, models.ErrCodeInvalidPasswordResetToken)
|
||||
assertHandlerErrorCode(t, err, user.ErrCodeInvalidPasswordResetToken)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ import (
|
|||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/modules/migration"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"os"
|
||||
|
@ -138,5 +140,7 @@ func initSchema(tx *xorm.Engine) error {
|
|||
schemeBeans := []interface{}{}
|
||||
schemeBeans = append(schemeBeans, models.GetTables()...)
|
||||
schemeBeans = append(schemeBeans, files.GetTables()...)
|
||||
schemeBeans = append(schemeBeans, migration.GetTables()...)
|
||||
schemeBeans = append(schemeBeans, user.GetTables()...)
|
||||
return tx.Sync2(schemeBeans...)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -9,7 +11,7 @@ func TestBulkTask_Update(t *testing.T) {
|
|||
IDs []int64
|
||||
Tasks []*Task
|
||||
Task Task
|
||||
User *User
|
||||
User *user.User
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -24,7 +26,7 @@ func TestBulkTask_Update(t *testing.T) {
|
|||
Task: Task{
|
||||
Text: "bulkupdated",
|
||||
},
|
||||
User: &User{ID: 1},
|
||||
User: &user.User{ID: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -34,7 +36,7 @@ func TestBulkTask_Update(t *testing.T) {
|
|||
Task: Task{
|
||||
Text: "bulkupdated",
|
||||
},
|
||||
User: &User{ID: 1},
|
||||
User: &user.User{ID: 1},
|
||||
},
|
||||
wantForbidden: true,
|
||||
},
|
||||
|
@ -45,13 +47,15 @@ func TestBulkTask_Update(t *testing.T) {
|
|||
Task: Task{
|
||||
Text: "bulkupdated",
|
||||
},
|
||||
User: &User{ID: 1},
|
||||
User: &user.User{ID: 1},
|
||||
},
|
||||
wantForbidden: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
bt := &BulkTask{
|
||||
IDs: tt.fields.IDs,
|
||||
Tasks: tt.fields.Tasks,
|
||||
|
|
|
@ -46,273 +46,6 @@ func (err ErrGenericForbidden) HTTPError() web.HTTPError {
|
|||
return web.HTTPError{HTTPCode: http.StatusForbidden, Code: ErrorCodeGenericForbidden, Message: "You're not allowed to do this."}
|
||||
}
|
||||
|
||||
// =====================
|
||||
// User Operation Errors
|
||||
// =====================
|
||||
|
||||
// ErrUsernameExists represents a "UsernameAlreadyExists" kind of error.
|
||||
type ErrUsernameExists struct {
|
||||
UserID int64
|
||||
Username string
|
||||
}
|
||||
|
||||
// IsErrUsernameExists checks if an error is a ErrUsernameExists.
|
||||
func IsErrUsernameExists(err error) bool {
|
||||
_, ok := err.(ErrUsernameExists)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUsernameExists) Error() string {
|
||||
return fmt.Sprintf("User with that username already exists [user id: %d, username: %s]", err.UserID, err.Username)
|
||||
}
|
||||
|
||||
// ErrorCodeUsernameExists holds the unique world-error code of this error
|
||||
const ErrorCodeUsernameExists = 1001
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrUsernameExists) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrorCodeUsernameExists, Message: "A user with this username already exists."}
|
||||
}
|
||||
|
||||
// ErrUserEmailExists represents a "UserEmailExists" kind of error.
|
||||
type ErrUserEmailExists struct {
|
||||
UserID int64
|
||||
Email string
|
||||
}
|
||||
|
||||
// IsErrUserEmailExists checks if an error is a ErrUserEmailExists.
|
||||
func IsErrUserEmailExists(err error) bool {
|
||||
_, ok := err.(ErrUserEmailExists)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUserEmailExists) Error() string {
|
||||
return fmt.Sprintf("User with that email already exists [user id: %d, email: %s]", err.UserID, err.Email)
|
||||
}
|
||||
|
||||
// ErrorCodeUserEmailExists holds the unique world-error code of this error
|
||||
const ErrorCodeUserEmailExists = 1002
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrUserEmailExists) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrorCodeUserEmailExists, Message: "A user with this email address already exists."}
|
||||
}
|
||||
|
||||
// ErrNoUsernamePassword represents a "NoUsernamePassword" kind of error.
|
||||
type ErrNoUsernamePassword struct{}
|
||||
|
||||
// IsErrNoUsernamePassword checks if an error is a ErrNoUsernamePassword.
|
||||
func IsErrNoUsernamePassword(err error) bool {
|
||||
_, ok := err.(ErrNoUsernamePassword)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrNoUsernamePassword) Error() string {
|
||||
return fmt.Sprintf("No username and password provided")
|
||||
}
|
||||
|
||||
// ErrCodeNoUsernamePassword holds the unique world-error code of this error
|
||||
const ErrCodeNoUsernamePassword = 1004
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrNoUsernamePassword) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeNoUsernamePassword, Message: "Please specify a username and a password."}
|
||||
}
|
||||
|
||||
// ErrUserDoesNotExist represents a "UserDoesNotExist" kind of error.
|
||||
type ErrUserDoesNotExist struct {
|
||||
UserID int64
|
||||
}
|
||||
|
||||
// IsErrUserDoesNotExist checks if an error is a ErrUserDoesNotExist.
|
||||
func IsErrUserDoesNotExist(err error) bool {
|
||||
_, ok := err.(ErrUserDoesNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUserDoesNotExist) Error() string {
|
||||
return fmt.Sprintf("User does not exist [user id: %d]", err.UserID)
|
||||
}
|
||||
|
||||
// ErrCodeUserDoesNotExist holds the unique world-error code of this error
|
||||
const ErrCodeUserDoesNotExist = 1005
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrUserDoesNotExist) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeUserDoesNotExist, Message: "The user does not exist."}
|
||||
}
|
||||
|
||||
// ErrCouldNotGetUserID represents a "ErrCouldNotGetUserID" kind of error.
|
||||
type ErrCouldNotGetUserID struct{}
|
||||
|
||||
// IsErrCouldNotGetUserID checks if an error is a ErrCouldNotGetUserID.
|
||||
func IsErrCouldNotGetUserID(err error) bool {
|
||||
_, ok := err.(ErrCouldNotGetUserID)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrCouldNotGetUserID) Error() string {
|
||||
return fmt.Sprintf("Could not get user ID")
|
||||
}
|
||||
|
||||
// ErrCodeCouldNotGetUserID holds the unique world-error code of this error
|
||||
const ErrCodeCouldNotGetUserID = 1006
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrCouldNotGetUserID) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeCouldNotGetUserID, Message: "Could not get user id."}
|
||||
}
|
||||
|
||||
// ErrNoPasswordResetToken represents an error where no password reset token exists for that user
|
||||
type ErrNoPasswordResetToken struct {
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (err ErrNoPasswordResetToken) Error() string {
|
||||
return fmt.Sprintf("No token to reset a password [UserID: %d]", err.UserID)
|
||||
}
|
||||
|
||||
// ErrCodeNoPasswordResetToken holds the unique world-error code of this error
|
||||
const ErrCodeNoPasswordResetToken = 1008
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrNoPasswordResetToken) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeNoPasswordResetToken, Message: "No token to reset a user's password provided."}
|
||||
}
|
||||
|
||||
// ErrInvalidPasswordResetToken is an error where the password reset token is invalid
|
||||
type ErrInvalidPasswordResetToken struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
func (err ErrInvalidPasswordResetToken) Error() string {
|
||||
return fmt.Sprintf("Invalid token to reset a password [Token: %s]", err.Token)
|
||||
}
|
||||
|
||||
// ErrCodeInvalidPasswordResetToken holds the unique world-error code of this error
|
||||
const ErrCodeInvalidPasswordResetToken = 1009
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrInvalidPasswordResetToken) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeInvalidPasswordResetToken, Message: "Invalid token to reset a user's password."}
|
||||
}
|
||||
|
||||
// IsErrInvalidPasswordResetToken checks if an error is a ErrInvalidPasswordResetToken.
|
||||
func IsErrInvalidPasswordResetToken(err error) bool {
|
||||
_, ok := err.(ErrInvalidPasswordResetToken)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrInvalidEmailConfirmToken is an error where the email confirm token is invalid
|
||||
type ErrInvalidEmailConfirmToken struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
func (err ErrInvalidEmailConfirmToken) Error() string {
|
||||
return fmt.Sprintf("Invalid email confirm token [Token: %s]", err.Token)
|
||||
}
|
||||
|
||||
// ErrCodeInvalidEmailConfirmToken holds the unique world-error code of this error
|
||||
const ErrCodeInvalidEmailConfirmToken = 1010
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrInvalidEmailConfirmToken) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeInvalidEmailConfirmToken, Message: "Invalid email confirm token."}
|
||||
}
|
||||
|
||||
// IsErrInvalidEmailConfirmToken checks if an error is a ErrInvalidEmailConfirmToken.
|
||||
func IsErrInvalidEmailConfirmToken(err error) bool {
|
||||
_, ok := err.(ErrInvalidEmailConfirmToken)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrWrongUsernameOrPassword is an error where the email was not confirmed
|
||||
type ErrWrongUsernameOrPassword struct {
|
||||
}
|
||||
|
||||
func (err ErrWrongUsernameOrPassword) Error() string {
|
||||
return fmt.Sprintf("Wrong username or password")
|
||||
}
|
||||
|
||||
// ErrCodeWrongUsernameOrPassword holds the unique world-error code of this error
|
||||
const ErrCodeWrongUsernameOrPassword = 1011
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrWrongUsernameOrPassword) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeWrongUsernameOrPassword, Message: "Wrong username or password."}
|
||||
}
|
||||
|
||||
// IsErrWrongUsernameOrPassword checks if an error is a IsErrEmailNotConfirmed.
|
||||
func IsErrWrongUsernameOrPassword(err error) bool {
|
||||
_, ok := err.(ErrWrongUsernameOrPassword)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrEmailNotConfirmed is an error where the email was not confirmed
|
||||
type ErrEmailNotConfirmed struct {
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (err ErrEmailNotConfirmed) Error() string {
|
||||
return fmt.Sprintf("Email is not confirmed [UserID: %d]", err.UserID)
|
||||
}
|
||||
|
||||
// ErrCodeEmailNotConfirmed holds the unique world-error code of this error
|
||||
const ErrCodeEmailNotConfirmed = 1012
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrEmailNotConfirmed) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeEmailNotConfirmed, Message: "Please confirm your email address."}
|
||||
}
|
||||
|
||||
// IsErrEmailNotConfirmed checks if an error is a IsErrEmailNotConfirmed.
|
||||
func IsErrEmailNotConfirmed(err error) bool {
|
||||
_, ok := err.(ErrEmailNotConfirmed)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrEmptyNewPassword represents a "EmptyNewPassword" kind of error.
|
||||
type ErrEmptyNewPassword struct{}
|
||||
|
||||
// IsErrEmptyNewPassword checks if an error is a ErrEmptyNewPassword.
|
||||
func IsErrEmptyNewPassword(err error) bool {
|
||||
_, ok := err.(ErrEmptyNewPassword)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrEmptyNewPassword) Error() string {
|
||||
return fmt.Sprintf("New password is empty")
|
||||
}
|
||||
|
||||
// ErrCodeEmptyNewPassword holds the unique world-error code of this error
|
||||
const ErrCodeEmptyNewPassword = 1013
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrEmptyNewPassword) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeEmptyNewPassword, Message: "Please specify new password."}
|
||||
}
|
||||
|
||||
// ErrEmptyOldPassword represents a "EmptyOldPassword" kind of error.
|
||||
type ErrEmptyOldPassword struct{}
|
||||
|
||||
// IsErrEmptyOldPassword checks if an error is a ErrEmptyOldPassword.
|
||||
func IsErrEmptyOldPassword(err error) bool {
|
||||
_, ok := err.(ErrEmptyOldPassword)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrEmptyOldPassword) Error() string {
|
||||
return fmt.Sprintf("Old password is empty")
|
||||
}
|
||||
|
||||
// ErrCodeEmptyOldPassword holds the unique world-error code of this error
|
||||
const ErrCodeEmptyOldPassword = 1014
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrEmptyOldPassword) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeEmptyOldPassword, Message: "Please specify old password."}
|
||||
}
|
||||
|
||||
// ===================
|
||||
// Empty things errors
|
||||
// ===================
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
../../files/fixtures/files.yml
|
|
@ -17,6 +17,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"time"
|
||||
)
|
||||
|
@ -34,7 +35,7 @@ type Label struct {
|
|||
|
||||
CreatedByID int64 `xorm:"int(11) not null" json:"-"`
|
||||
// The user who created this label
|
||||
CreatedBy *User `xorm:"-" json:"created_by"`
|
||||
CreatedBy *user.User `xorm:"-" json:"created_by"`
|
||||
|
||||
// A unix timestamp when this label was created. You cannot change this value.
|
||||
Created int64 `xorm:"created not null" json:"created"`
|
||||
|
@ -63,7 +64,7 @@ func (Label) TableName() string {
|
|||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /labels [put]
|
||||
func (l *Label) Create(a web.Auth) (err error) {
|
||||
u, err := getUserWithError(a)
|
||||
u, err := user.GetFromAuth(a)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -136,7 +137,7 @@ func (l *Label) ReadAll(a web.Auth, search string, page int, perPage int) (ls in
|
|||
return nil, 0, 0, ErrGenericForbidden{}
|
||||
}
|
||||
|
||||
u := &User{ID: a.GetID()}
|
||||
u := &user.User{ID: a.GetID()}
|
||||
|
||||
// Get all tasks
|
||||
taskIDs, err := getUserTaskIDs(u)
|
||||
|
@ -175,7 +176,7 @@ func (l *Label) ReadOne() (err error) {
|
|||
}
|
||||
*l = *label
|
||||
|
||||
user, err := GetUserByID(l.CreatedByID)
|
||||
user, err := user.GetUserByID(l.CreatedByID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -198,7 +199,7 @@ func getLabelByIDSimple(labelID int64) (*Label, error) {
|
|||
}
|
||||
|
||||
// Helper method to get all task ids a user has
|
||||
func getUserTaskIDs(u *User) (taskIDs []int64, err error) {
|
||||
func getUserTaskIDs(u *user.User) (taskIDs []int64, err error) {
|
||||
|
||||
// Get all lists
|
||||
lists, _, _, err := getRawListsForUser("", u, -1, 0)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/go-xorm/builder"
|
||||
)
|
||||
|
@ -65,7 +66,7 @@ func (l *Label) hasAccessToLabel(a web.Auth) (bool, error) {
|
|||
// TODO: add an extra check for link share handling
|
||||
|
||||
// Get all tasks
|
||||
taskIDs, err := getUserTaskIDs(&User{ID: a.GetID()})
|
||||
taskIDs, err := getUserTaskIDs(&user.User{ID: a.GetID()})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/go-xorm/builder"
|
||||
)
|
||||
|
@ -120,7 +121,7 @@ func (lt *LabelTask) ReadAll(a web.Auth, search string, page int, perPage int) (
|
|||
}
|
||||
|
||||
return getLabelsByTaskIDs(&LabelByTaskIDsOptions{
|
||||
User: &User{ID: a.GetID()},
|
||||
User: &user.User{ID: a.GetID()},
|
||||
Search: search,
|
||||
Page: page,
|
||||
TaskIDs: []int64{lt.TaskID},
|
||||
|
@ -135,7 +136,7 @@ type labelWithTaskID struct {
|
|||
|
||||
// LabelByTaskIDsOptions is a struct to not clutter the function with too many optional parameters.
|
||||
type LabelByTaskIDsOptions struct {
|
||||
User *User
|
||||
User *user.User
|
||||
Search string
|
||||
Page int
|
||||
PerPage int
|
||||
|
@ -185,7 +186,7 @@ func getLabelsByTaskIDs(opts *LabelByTaskIDsOptions) (ls []*labelWithTaskID, res
|
|||
for _, l := range labels {
|
||||
userids = append(userids, l.CreatedByID)
|
||||
}
|
||||
users := make(map[int64]*User)
|
||||
users := make(map[int64]*user.User)
|
||||
err = x.In("id", userids).Find(&users)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
|
@ -290,7 +291,7 @@ func (t *Task) updateTaskLabels(creator web.Auth, labels []*Label) (err error) {
|
|||
return err
|
||||
}
|
||||
if !hasAccessToLabel {
|
||||
user, _ := creator.(*User)
|
||||
user, _ := creator.(*user.User)
|
||||
return ErrUserHasNoAccessToLabel{LabelID: l.ID, UserID: user.ID}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
@ -37,7 +39,7 @@ func TestLabelTask_ReadAll(t *testing.T) {
|
|||
TaskID: 1,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
wantLabels: []*labelWithTaskID{
|
||||
{
|
||||
|
@ -46,7 +48,7 @@ func TestLabelTask_ReadAll(t *testing.T) {
|
|||
ID: 4,
|
||||
Title: "Label #4 - visible via other task",
|
||||
CreatedByID: 2,
|
||||
CreatedBy: &User{
|
||||
CreatedBy: &user.User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -62,7 +64,7 @@ func TestLabelTask_ReadAll(t *testing.T) {
|
|||
TaskID: 14,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrNoRightToSeeTask,
|
||||
|
@ -73,7 +75,7 @@ func TestLabelTask_ReadAll(t *testing.T) {
|
|||
TaskID: 9999,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrTaskDoesNotExist,
|
||||
|
@ -81,6 +83,8 @@ func TestLabelTask_ReadAll(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
l := &LabelTask{
|
||||
ID: tt.fields.ID,
|
||||
TaskID: tt.fields.TaskID,
|
||||
|
@ -131,17 +135,17 @@ func TestLabelTask_Create(t *testing.T) {
|
|||
LabelID: 1,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "already existing",
|
||||
fields: fields{
|
||||
TaskID: 1,
|
||||
LabelID: 1,
|
||||
LabelID: 4,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrLabelIsAlreadyOnTask,
|
||||
|
@ -153,7 +157,7 @@ func TestLabelTask_Create(t *testing.T) {
|
|||
LabelID: 9999,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
wantForbidden: true,
|
||||
},
|
||||
|
@ -164,7 +168,7 @@ func TestLabelTask_Create(t *testing.T) {
|
|||
LabelID: 1,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
wantForbidden: true,
|
||||
wantErr: true,
|
||||
|
@ -173,6 +177,8 @@ func TestLabelTask_Create(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
l := &LabelTask{
|
||||
ID: tt.fields.ID,
|
||||
TaskID: tt.fields.TaskID,
|
||||
|
@ -217,9 +223,9 @@ func TestLabelTask_Delete(t *testing.T) {
|
|||
name: "normal",
|
||||
fields: fields{
|
||||
TaskID: 1,
|
||||
LabelID: 1,
|
||||
LabelID: 4,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
},
|
||||
{
|
||||
name: "delete nonexistant",
|
||||
|
@ -227,7 +233,7 @@ func TestLabelTask_Delete(t *testing.T) {
|
|||
TaskID: 1,
|
||||
LabelID: 1,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
},
|
||||
{
|
||||
|
@ -236,7 +242,7 @@ func TestLabelTask_Delete(t *testing.T) {
|
|||
TaskID: 1,
|
||||
LabelID: 9999,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
},
|
||||
{
|
||||
|
@ -245,7 +251,7 @@ func TestLabelTask_Delete(t *testing.T) {
|
|||
TaskID: 9999,
|
||||
LabelID: 1,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
},
|
||||
{
|
||||
|
@ -254,12 +260,14 @@ func TestLabelTask_Delete(t *testing.T) {
|
|||
TaskID: 14,
|
||||
LabelID: 1,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
l := &LabelTask{
|
||||
ID: tt.fields.ID,
|
||||
TaskID: tt.fields.TaskID,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
@ -32,7 +33,7 @@ func TestLabel_ReadAll(t *testing.T) {
|
|||
Description string
|
||||
HexColor string
|
||||
CreatedByID int64
|
||||
CreatedBy *User
|
||||
CreatedBy *user.User
|
||||
Created int64
|
||||
Updated int64
|
||||
CRUDable web.CRUDable
|
||||
|
@ -43,7 +44,7 @@ func TestLabel_ReadAll(t *testing.T) {
|
|||
a web.Auth
|
||||
page int
|
||||
}
|
||||
user1 := &User{
|
||||
user1 := &user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -60,7 +61,7 @@ func TestLabel_ReadAll(t *testing.T) {
|
|||
{
|
||||
name: "normal",
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
wantLs: []*labelWithTaskID{
|
||||
{
|
||||
|
@ -85,7 +86,7 @@ func TestLabel_ReadAll(t *testing.T) {
|
|||
ID: 4,
|
||||
Title: "Label #4 - visible via other task",
|
||||
CreatedByID: 2,
|
||||
CreatedBy: &User{
|
||||
CreatedBy: &user.User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -98,7 +99,7 @@ func TestLabel_ReadAll(t *testing.T) {
|
|||
{
|
||||
name: "invalid user",
|
||||
args: args{
|
||||
a: &User{ID: -1},
|
||||
a: &user.User{ID: -1},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
|
@ -136,13 +137,13 @@ func TestLabel_ReadOne(t *testing.T) {
|
|||
Description string
|
||||
HexColor string
|
||||
CreatedByID int64
|
||||
CreatedBy *User
|
||||
CreatedBy *user.User
|
||||
Created int64
|
||||
Updated int64
|
||||
CRUDable web.CRUDable
|
||||
Rights web.Rights
|
||||
}
|
||||
user1 := &User{
|
||||
user1 := &user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -169,7 +170,7 @@ func TestLabel_ReadOne(t *testing.T) {
|
|||
CreatedByID: 1,
|
||||
CreatedBy: user1,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
},
|
||||
{
|
||||
name: "Get nonexistant label",
|
||||
|
@ -179,7 +180,7 @@ func TestLabel_ReadOne(t *testing.T) {
|
|||
wantErr: true,
|
||||
errType: IsErrLabelDoesNotExist,
|
||||
wantForbidden: true,
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
},
|
||||
{
|
||||
name: "no rights",
|
||||
|
@ -187,7 +188,7 @@ func TestLabel_ReadOne(t *testing.T) {
|
|||
ID: 3,
|
||||
},
|
||||
wantForbidden: true,
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
},
|
||||
{
|
||||
name: "Get label #4 - other user",
|
||||
|
@ -198,14 +199,14 @@ func TestLabel_ReadOne(t *testing.T) {
|
|||
ID: 4,
|
||||
Title: "Label #4 - visible via other task",
|
||||
CreatedByID: 2,
|
||||
CreatedBy: &User{
|
||||
CreatedBy: &user.User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f",
|
||||
},
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
@ -248,7 +249,7 @@ func TestLabel_Create(t *testing.T) {
|
|||
Description string
|
||||
HexColor string
|
||||
CreatedByID int64
|
||||
CreatedBy *User
|
||||
CreatedBy *user.User
|
||||
Created int64
|
||||
Updated int64
|
||||
CRUDable web.CRUDable
|
||||
|
@ -272,7 +273,7 @@ func TestLabel_Create(t *testing.T) {
|
|||
HexColor: "ffccff",
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -308,7 +309,7 @@ func TestLabel_Update(t *testing.T) {
|
|||
Description string
|
||||
HexColor string
|
||||
CreatedByID int64
|
||||
CreatedBy *User
|
||||
CreatedBy *user.User
|
||||
Created int64
|
||||
Updated int64
|
||||
CRUDable web.CRUDable
|
||||
|
@ -327,7 +328,7 @@ func TestLabel_Update(t *testing.T) {
|
|||
ID: 1,
|
||||
Title: "new and better",
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
},
|
||||
{
|
||||
name: "nonexisting",
|
||||
|
@ -335,7 +336,7 @@ func TestLabel_Update(t *testing.T) {
|
|||
ID: 99999,
|
||||
Title: "new and better",
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
wantErr: true,
|
||||
},
|
||||
|
@ -345,7 +346,7 @@ func TestLabel_Update(t *testing.T) {
|
|||
ID: 3,
|
||||
Title: "new and better",
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
},
|
||||
{
|
||||
|
@ -354,7 +355,7 @@ func TestLabel_Update(t *testing.T) {
|
|||
ID: 4,
|
||||
Title: "new and better",
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
},
|
||||
}
|
||||
|
@ -390,7 +391,7 @@ func TestLabel_Delete(t *testing.T) {
|
|||
Description string
|
||||
HexColor string
|
||||
CreatedByID int64
|
||||
CreatedBy *User
|
||||
CreatedBy *user.User
|
||||
Created int64
|
||||
Updated int64
|
||||
CRUDable web.CRUDable
|
||||
|
@ -409,14 +410,14 @@ func TestLabel_Delete(t *testing.T) {
|
|||
fields: fields{
|
||||
ID: 1,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
},
|
||||
{
|
||||
name: "nonexisting",
|
||||
fields: fields{
|
||||
ID: 99999,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true, // When the label does not exist, it is forbidden. We should fix this, but for everything.
|
||||
},
|
||||
{
|
||||
|
@ -424,7 +425,7 @@ func TestLabel_Delete(t *testing.T) {
|
|||
fields: fields{
|
||||
ID: 3,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
},
|
||||
{
|
||||
|
@ -432,7 +433,7 @@ func TestLabel_Delete(t *testing.T) {
|
|||
fields: fields{
|
||||
ID: 4,
|
||||
},
|
||||
auth: &User{ID: 1},
|
||||
auth: &user.User{ID: 1},
|
||||
wantForbidden: true,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
|
@ -48,8 +49,8 @@ type LinkSharing struct {
|
|||
SharingType SharingType `xorm:"int(11) INDEX not null default 0" json:"sharing_type" valid:"length(0|2)" maximum:"2" default:"0"`
|
||||
|
||||
// The user who shared this list
|
||||
SharedBy *User `xorm:"-" json:"shared_by"`
|
||||
SharedByID int64 `xorm:"int(11) INDEX not null" json:"-"`
|
||||
SharedBy *user.User `xorm:"-" json:"shared_by"`
|
||||
SharedByID int64 `xorm:"int(11) INDEX not null" json:"-"`
|
||||
|
||||
// A unix timestamp when this list was shared. You cannot change this value.
|
||||
Created int64 `xorm:"created not null" json:"created"`
|
||||
|
@ -100,7 +101,7 @@ func (share *LinkSharing) Create(a web.Auth) (err error) {
|
|||
share.SharedByID = a.GetID()
|
||||
share.Hash = utils.MakeRandomString(40)
|
||||
_, err = x.Insert(share)
|
||||
share.SharedBy, _ = a.(*User)
|
||||
share.SharedBy, _ = a.(*user.User)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -168,7 +169,7 @@ func (share *LinkSharing) ReadAll(a web.Auth, search string, page int, perPage i
|
|||
userIDs = append(userIDs, s.SharedByID)
|
||||
}
|
||||
|
||||
users := make(map[int64]*User)
|
||||
users := make(map[int64]*user.User)
|
||||
err = x.In("id", userIDs).Find(&users)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
|
|
|
@ -18,6 +18,7 @@ package models
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/metrics"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
)
|
||||
|
||||
|
@ -36,7 +37,7 @@ type List struct {
|
|||
NamespaceID int64 `xorm:"int(11) INDEX not null" json:"-" param:"namespace"`
|
||||
|
||||
// The user who created this list.
|
||||
Owner *User `xorm:"-" json:"owner" valid:"-"`
|
||||
Owner *user.User `xorm:"-" json:"owner" valid:"-"`
|
||||
// An array of tasks which belong to the list.
|
||||
// Deprecated: you should use the dedicated task list endpoint because it has support for pagination and filtering
|
||||
Tasks []*Task `xorm:"-" json:"-"`
|
||||
|
@ -51,7 +52,7 @@ type List struct {
|
|||
}
|
||||
|
||||
// GetListsByNamespaceID gets all lists in a namespace
|
||||
func GetListsByNamespaceID(nID int64, doer *User) (lists []*List, err error) {
|
||||
func GetListsByNamespaceID(nID int64, doer *user.User) (lists []*List, err error) {
|
||||
if nID == -1 {
|
||||
err = x.Select("l.*").
|
||||
Table("list").
|
||||
|
@ -103,7 +104,7 @@ func (l *List) ReadAll(a web.Auth, search string, page int, perPage int) (result
|
|||
return lists, 0, 0, err
|
||||
}
|
||||
|
||||
lists, resultCount, totalItems, err := getRawListsForUser(search, &User{ID: a.GetID()}, page, perPage)
|
||||
lists, resultCount, totalItems, err := getRawListsForUser(search, &user.User{ID: a.GetID()}, page, perPage)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
@ -127,7 +128,7 @@ func (l *List) ReadAll(a web.Auth, search string, page int, perPage int) (result
|
|||
// @Router /lists/{id} [get]
|
||||
func (l *List) ReadOne() (err error) {
|
||||
// Get list owner
|
||||
l.Owner, err = GetUserByID(l.OwnerID)
|
||||
l.Owner, err = user.GetUserByID(l.OwnerID)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -176,8 +177,8 @@ func GetListSimplByTaskID(taskID int64) (l *List, err error) {
|
|||
}
|
||||
|
||||
// Gets the lists only, without any tasks or so
|
||||
func getRawListsForUser(search string, u *User, page int, perPage int) (lists []*List, resultCount int, totalItems int64, err error) {
|
||||
fullUser, err := GetUserByID(u.ID)
|
||||
func getRawListsForUser(search string, u *user.User, page int, perPage int) (lists []*List, resultCount int, totalItems int64, err error) {
|
||||
fullUser, err := user.GetUserByID(u.ID)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
@ -237,7 +238,7 @@ func AddListDetails(lists []*List) (err error) {
|
|||
}
|
||||
|
||||
// Get all list owners
|
||||
owners := []*User{}
|
||||
owners := []*user.User{}
|
||||
err = x.In("id", ownerIDs).Find(&owners)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -348,7 +349,7 @@ func updateListByTaskID(taskID int64) (err error) {
|
|||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /namespaces/{namespaceID}/lists [put]
|
||||
func (l *List) Create(a web.Auth) (err error) {
|
||||
doer, err := getUserWithError(a)
|
||||
doer, err := user.GetFromAuth(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/go-xorm/builder"
|
||||
)
|
||||
|
@ -39,7 +40,7 @@ func (l *List) CanWrite(a web.Auth) (bool, error) {
|
|||
}
|
||||
|
||||
// Check if the user is either owner or can write to the list
|
||||
if originalList.isOwner(&User{ID: a.GetID()}) {
|
||||
if originalList.isOwner(&user.User{ID: a.GetID()}) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
|
@ -60,7 +61,7 @@ func (l *List) CanRead(a web.Auth) (bool, error) {
|
|||
(shareAuth.Right == RightRead || shareAuth.Right == RightWrite || shareAuth.Right == RightAdmin), nil
|
||||
}
|
||||
|
||||
if l.isOwner(&User{ID: a.GetID()}) {
|
||||
if l.isOwner(&user.User{ID: a.GetID()}) {
|
||||
return true, nil
|
||||
}
|
||||
return l.checkRight(a, RightRead, RightWrite, RightAdmin)
|
||||
|
@ -100,14 +101,14 @@ func (l *List) IsAdmin(a web.Auth) (bool, error) {
|
|||
// Check all the things
|
||||
// Check if the user is either owner or can write to the list
|
||||
// Owners are always admins
|
||||
if originalList.isOwner(&User{ID: a.GetID()}) {
|
||||
if originalList.isOwner(&user.User{ID: a.GetID()}) {
|
||||
return true, nil
|
||||
}
|
||||
return originalList.checkRight(a, RightAdmin)
|
||||
}
|
||||
|
||||
// Little helper function to check if a user is list owner
|
||||
func (l *List) isOwner(u *User) bool {
|
||||
func (l *List) isOwner(u *user.User) bool {
|
||||
return l.OwnerID == u.ID
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
|
@ -25,6 +27,8 @@ import (
|
|||
)
|
||||
|
||||
func TestTeamList(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
// Dummy relation
|
||||
tl := TeamList{
|
||||
TeamID: 1,
|
||||
|
@ -33,7 +37,7 @@ func TestTeamList(t *testing.T) {
|
|||
}
|
||||
|
||||
// Dummyuser
|
||||
u, err := GetUserByID(1)
|
||||
u, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check normal creation
|
||||
|
@ -164,6 +168,8 @@ func TestTeamList_Update(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
tl := &TeamList{
|
||||
ID: tt.fields.ID,
|
||||
TeamID: tt.fields.TeamID,
|
||||
|
|
|
@ -17,13 +17,15 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestList_CreateOrUpdate(t *testing.T) {
|
||||
user := &User{
|
||||
usr := &user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Email: "user1@example.com",
|
||||
|
@ -31,41 +33,41 @@ func TestList_CreateOrUpdate(t *testing.T) {
|
|||
|
||||
t.Run("create", func(t *testing.T) {
|
||||
t.Run("normal", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
list := List{
|
||||
Title: "test",
|
||||
Description: "Lorem Ipsum",
|
||||
NamespaceID: 1,
|
||||
}
|
||||
err := list.Create(user)
|
||||
err := list.Create(usr)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("nonexistant namespace", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
list := List{
|
||||
Title: "test",
|
||||
Description: "Lorem Ipsum",
|
||||
NamespaceID: 999999,
|
||||
}
|
||||
|
||||
err := list.Create(user)
|
||||
err := list.Create(usr)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||
})
|
||||
t.Run("nonexistant owner", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
user := &User{ID: 9482385}
|
||||
db.LoadAndAssertFixtures(t)
|
||||
usr := &user.User{ID: 9482385}
|
||||
list := List{
|
||||
Title: "test",
|
||||
Description: "Lorem Ipsum",
|
||||
NamespaceID: 1,
|
||||
}
|
||||
err := list.Create(user)
|
||||
err := list.Create(usr)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, user.IsErrUserDoesNotExist(err))
|
||||
})
|
||||
t.Run("existing identifier", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
list := List{
|
||||
Title: "test",
|
||||
Description: "Lorem Ipsum",
|
||||
|
@ -73,7 +75,7 @@ func TestList_CreateOrUpdate(t *testing.T) {
|
|||
NamespaceID: 1,
|
||||
}
|
||||
|
||||
err := list.Create(user)
|
||||
err := list.Create(usr)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListIdentifierIsNotUnique(err))
|
||||
})
|
||||
|
@ -81,7 +83,7 @@ func TestList_CreateOrUpdate(t *testing.T) {
|
|||
|
||||
t.Run("update", func(t *testing.T) {
|
||||
t.Run("normal", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
list := List{
|
||||
ID: 1,
|
||||
Title: "test",
|
||||
|
@ -94,7 +96,7 @@ func TestList_CreateOrUpdate(t *testing.T) {
|
|||
|
||||
})
|
||||
t.Run("nonexistant", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
list := List{
|
||||
ID: 99999999,
|
||||
Title: "test",
|
||||
|
@ -105,7 +107,7 @@ func TestList_CreateOrUpdate(t *testing.T) {
|
|||
|
||||
})
|
||||
t.Run("existing identifier", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
list := List{
|
||||
Title: "test",
|
||||
Description: "Lorem Ipsum",
|
||||
|
@ -113,7 +115,7 @@ func TestList_CreateOrUpdate(t *testing.T) {
|
|||
NamespaceID: 1,
|
||||
}
|
||||
|
||||
err := list.Create(user)
|
||||
err := list.Create(usr)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListIdentifierIsNotUnique(err))
|
||||
})
|
||||
|
@ -121,7 +123,7 @@ func TestList_CreateOrUpdate(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestList_Delete(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
list := List{
|
||||
ID: 1,
|
||||
}
|
||||
|
@ -131,14 +133,16 @@ func TestList_Delete(t *testing.T) {
|
|||
|
||||
func TestList_ReadAll(t *testing.T) {
|
||||
t.Run("all in namespace", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
// Get all lists for our namespace
|
||||
lists, err := GetListsByNamespaceID(1, &User{})
|
||||
lists, err := GetListsByNamespaceID(1, &user.User{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, len(lists), 2)
|
||||
})
|
||||
t.Run("all lists for user", func(t *testing.T) {
|
||||
u := &User{ID: 1}
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
u := &user.User{ID: 1}
|
||||
list := List{}
|
||||
lists3, _, _, err := list.ReadAll(u, "", 1, 50)
|
||||
|
||||
|
@ -148,10 +152,12 @@ func TestList_ReadAll(t *testing.T) {
|
|||
assert.Equal(t, 16, s.Len())
|
||||
})
|
||||
t.Run("lists for nonexistant user", func(t *testing.T) {
|
||||
user := &User{ID: 999999}
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
usr := &user.User{ID: 999999}
|
||||
list := List{}
|
||||
_, _, _, err := list.ReadAll(user, "", 1, 50)
|
||||
_, _, _, err := list.ReadAll(usr, "", 1, 50)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, user.IsErrUserDoesNotExist(err))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
package models
|
||||
|
||||
import "code.vikunja.io/web"
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
)
|
||||
|
||||
// ListUser represents a list <-> user relation
|
||||
type ListUser struct {
|
||||
|
@ -47,8 +50,8 @@ func (ListUser) TableName() string {
|
|||
|
||||
// UserWithRight represents a user in combination with the right it can have on a list/namespace
|
||||
type UserWithRight struct {
|
||||
User `xorm:"extends"`
|
||||
Right Right `json:"right"`
|
||||
user.User `xorm:"extends"`
|
||||
Right Right `json:"right"`
|
||||
}
|
||||
|
||||
// Create creates a new list <-> user relation
|
||||
|
@ -80,7 +83,7 @@ func (lu *ListUser) Create(a web.Auth) (err error) {
|
|||
}
|
||||
|
||||
// Check if the user exists
|
||||
user, err := GetUserByUsername(lu.Username)
|
||||
user, err := user.GetUserByUsername(lu.Username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -126,7 +129,7 @@ func (lu *ListUser) Create(a web.Auth) (err error) {
|
|||
func (lu *ListUser) Delete() (err error) {
|
||||
|
||||
// Check if the user exists
|
||||
user, err := GetUserByUsername(lu.Username)
|
||||
user, err := user.GetUserByUsername(lu.Username)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -227,7 +230,7 @@ func (lu *ListUser) Update() (err error) {
|
|||
}
|
||||
|
||||
// Check if the user exists
|
||||
user, err := GetUserByUsername(lu.Username)
|
||||
user, err := user.GetUserByUsername(lu.Username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/web"
|
||||
|
@ -48,7 +50,7 @@ func TestListUser_CanDoSomething(t *testing.T) {
|
|||
ListID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 3},
|
||||
a: &user.User{ID: 3},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": true, "CanDelete": true, "CanUpdate": true},
|
||||
},
|
||||
|
@ -58,7 +60,7 @@ func TestListUser_CanDoSomething(t *testing.T) {
|
|||
ListID: 300,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 3},
|
||||
a: &user.User{ID: 3},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false},
|
||||
},
|
||||
|
@ -68,13 +70,15 @@ func TestListUser_CanDoSomething(t *testing.T) {
|
|||
ListID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 4},
|
||||
a: &user.User{ID: 4},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
lu := &ListUser{
|
||||
ID: tt.fields.ID,
|
||||
UserID: tt.fields.UserID,
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
@ -58,7 +60,7 @@ func TestListUser_Create(t *testing.T) {
|
|||
name: "ListUsers Create for duplicate",
|
||||
fields: fields{
|
||||
Username: "user1",
|
||||
ListID: 2,
|
||||
ListID: 3,
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrUserAlreadyHasAccess,
|
||||
|
@ -89,7 +91,7 @@ func TestListUser_Create(t *testing.T) {
|
|||
ListID: 2,
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrUserDoesNotExist,
|
||||
errType: user.IsErrUserDoesNotExist,
|
||||
},
|
||||
{
|
||||
name: "ListUsers Create with the owner as shared user",
|
||||
|
@ -103,6 +105,8 @@ func TestListUser_Create(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
ul := &ListUser{
|
||||
ID: tt.fields.ID,
|
||||
UserID: tt.fields.UserID,
|
||||
|
@ -155,11 +159,11 @@ func TestListUser_ReadAll(t *testing.T) {
|
|||
ListID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 3},
|
||||
a: &user.User{ID: 3},
|
||||
},
|
||||
want: []*UserWithRight{
|
||||
{
|
||||
User: User{
|
||||
User: user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -169,7 +173,7 @@ func TestListUser_ReadAll(t *testing.T) {
|
|||
Right: RightRead,
|
||||
},
|
||||
{
|
||||
User: User{
|
||||
User: user.User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -185,7 +189,7 @@ func TestListUser_ReadAll(t *testing.T) {
|
|||
ListID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 4},
|
||||
a: &user.User{ID: 4},
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrNeedToHaveListReadAccess,
|
||||
|
@ -193,6 +197,8 @@ func TestListUser_ReadAll(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
ul := &ListUser{
|
||||
ID: tt.fields.ID,
|
||||
UserID: tt.fields.UserID,
|
||||
|
@ -271,6 +277,8 @@ func TestListUser_Update(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
lu := &ListUser{
|
||||
ID: tt.fields.ID,
|
||||
Username: tt.fields.Username,
|
||||
|
@ -316,7 +324,7 @@ func TestListUser_Delete(t *testing.T) {
|
|||
ListID: 2,
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrUserDoesNotExist,
|
||||
errType: user.IsErrUserDoesNotExist,
|
||||
},
|
||||
{
|
||||
name: "Try deleting a user which does not has access but exists",
|
||||
|
@ -337,6 +345,8 @@ func TestListUser_Delete(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
lu := &ListUser{
|
||||
ID: tt.fields.ID,
|
||||
Username: tt.fields.Username,
|
||||
|
|
|
@ -19,6 +19,7 @@ package models
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
@ -33,7 +34,9 @@ func TestMain(m *testing.M) {
|
|||
// Some tests use the file engine, so we'll need to initialize that
|
||||
files.InitTests()
|
||||
|
||||
SetupTests(config.ServiceRootpath.GetString())
|
||||
user.InitTests()
|
||||
|
||||
SetupTests()
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
_ "github.com/go-sql-driver/mysql" // Because.
|
||||
"github.com/go-xorm/xorm"
|
||||
|
||||
|
@ -33,7 +34,7 @@ var (
|
|||
// GetTables returns all structs which are also a table.
|
||||
func GetTables() []interface{} {
|
||||
return []interface{}{
|
||||
&User{},
|
||||
&user.User{},
|
||||
&List{},
|
||||
&Task{},
|
||||
&Team{},
|
||||
|
|
|
@ -18,6 +18,7 @@ package models
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/metrics"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/imdario/mergo"
|
||||
"time"
|
||||
|
@ -34,7 +35,7 @@ type Namespace struct {
|
|||
OwnerID int64 `xorm:"int(11) not null INDEX" json:"-"`
|
||||
|
||||
// The user who owns this namespace
|
||||
Owner *User `xorm:"-" json:"owner" valid:"-"`
|
||||
Owner *user.User `xorm:"-" json:"owner" valid:"-"`
|
||||
|
||||
// A unix timestamp when this namespace was created. You cannot change this value.
|
||||
Created int64 `xorm:"created not null" json:"created"`
|
||||
|
@ -97,7 +98,7 @@ func GetNamespaceByID(id int64) (namespace Namespace, err error) {
|
|||
}
|
||||
|
||||
// Get the namespace Owner
|
||||
namespace.Owner, err = GetUserByID(namespace.OwnerID)
|
||||
namespace.Owner, err = user.GetUserByID(namespace.OwnerID)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -115,7 +116,7 @@ func GetNamespaceByID(id int64) (namespace Namespace, err error) {
|
|||
// @Router /namespaces/{id} [get]
|
||||
func (n *Namespace) ReadOne() (err error) {
|
||||
// Get the namespace Owner
|
||||
n.Owner, err = GetUserByID(n.OwnerID)
|
||||
n.Owner, err = user.GetUserByID(n.OwnerID)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -143,7 +144,7 @@ func (n *Namespace) ReadAll(a web.Auth, search string, page int, perPage int) (r
|
|||
return nil, 0, 0, ErrGenericForbidden{}
|
||||
}
|
||||
|
||||
doer, err := getUserWithError(a)
|
||||
doer, err := user.GetFromAuth(a)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
@ -176,7 +177,7 @@ func (n *Namespace) ReadAll(a web.Auth, search string, page int, perPage int) (r
|
|||
}
|
||||
|
||||
// Get all users
|
||||
users := []*User{}
|
||||
users := []*user.User{}
|
||||
err = x.Select("users.*").
|
||||
Table("namespaces").
|
||||
Join("LEFT", "team_namespaces", "namespaces.id = team_namespaces.namespace_id").
|
||||
|
@ -301,7 +302,7 @@ func (n *Namespace) Create(a web.Auth) (err error) {
|
|||
n.ID = 0 // This would otherwise prevent the creation of new lists after one was created
|
||||
|
||||
// Check if the User exists
|
||||
n.Owner, err = GetUserByID(a.GetID())
|
||||
n.Owner, err = user.GetUserByID(a.GetID())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -343,7 +344,7 @@ func (n *Namespace) Delete() (err error) {
|
|||
}
|
||||
|
||||
// Delete all lists with their tasks
|
||||
lists, err := GetListsByNamespaceID(n.ID, &User{})
|
||||
lists, err := GetListsByNamespaceID(n.ID, &user.User{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -401,7 +402,7 @@ func (n *Namespace) Update() (err error) {
|
|||
// Check if the (new) owner exists
|
||||
n.OwnerID = n.Owner.ID
|
||||
if currentNamespace.OwnerID != n.OwnerID {
|
||||
n.Owner, err = GetUserByID(n.OwnerID)
|
||||
n.Owner, err = user.GetUserByID(n.OwnerID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/web"
|
||||
|
@ -48,7 +50,7 @@ func TestTeamNamespace_CanDoSomething(t *testing.T) {
|
|||
NamespaceID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 3},
|
||||
a: &user.User{ID: 3},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": true, "CanDelete": true, "CanUpdate": true},
|
||||
},
|
||||
|
@ -58,7 +60,7 @@ func TestTeamNamespace_CanDoSomething(t *testing.T) {
|
|||
NamespaceID: 300,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 3},
|
||||
a: &user.User{ID: 3},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false},
|
||||
},
|
||||
|
@ -68,13 +70,15 @@ func TestTeamNamespace_CanDoSomething(t *testing.T) {
|
|||
NamespaceID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 4},
|
||||
a: &user.User{ID: 4},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
tn := &TeamNamespace{
|
||||
ID: tt.fields.ID,
|
||||
TeamID: tt.fields.TeamID,
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
|
@ -25,6 +27,8 @@ import (
|
|||
)
|
||||
|
||||
func TestTeamNamespace(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
// Dummy team <-> namespace relation
|
||||
tn := TeamNamespace{
|
||||
TeamID: 1,
|
||||
|
@ -32,7 +36,7 @@ func TestTeamNamespace(t *testing.T) {
|
|||
Right: RightAdmin,
|
||||
}
|
||||
|
||||
dummyuser, err := GetUserByID(1)
|
||||
dummyuser, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Test normal creation
|
||||
|
@ -80,7 +84,7 @@ func TestTeamNamespace(t *testing.T) {
|
|||
assert.True(t, IsErrNamespaceDoesNotExist(err))
|
||||
|
||||
// Check with no right to read the namespace
|
||||
nouser := &User{ID: 393}
|
||||
nouser := &user.User{ID: 393}
|
||||
_, _, _, err = tn.ReadAll(nouser, "", 1, 50)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNeedToHaveNamespaceReadAccess(err))
|
||||
|
@ -156,6 +160,8 @@ func TestTeamNamespace_Update(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
tl := &TeamNamespace{
|
||||
ID: tt.fields.ID,
|
||||
TeamID: tt.fields.TeamID,
|
||||
|
|
|
@ -17,12 +17,16 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNamespace_Create(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
// Create test database
|
||||
//assert.NoError(t, LoadFixtures())
|
||||
|
||||
|
@ -33,7 +37,7 @@ func TestNamespace_Create(t *testing.T) {
|
|||
}
|
||||
|
||||
// Doer
|
||||
doer, err := GetUserByID(1)
|
||||
doer, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try creating it
|
||||
|
@ -57,11 +61,11 @@ func TestNamespace_Create(t *testing.T) {
|
|||
assert.True(t, IsErrNamespaceNameCannotBeEmpty(err))
|
||||
|
||||
// Try inserting one with a nonexistant user
|
||||
nUser := &User{ID: 9482385}
|
||||
nUser := &user.User{ID: 9482385}
|
||||
dnsp2 := dummynamespace
|
||||
err = dnsp2.Create(nUser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, user.IsErrUserDoesNotExist(err))
|
||||
|
||||
// Update it
|
||||
allowed, err = dummynamespace.CanUpdate(doer)
|
||||
|
@ -85,7 +89,7 @@ func TestNamespace_Create(t *testing.T) {
|
|||
dummynamespace.Owner.ID = 94829838572
|
||||
err = dummynamespace.Update()
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, user.IsErrUserDoesNotExist(err))
|
||||
|
||||
// Try updating without a name
|
||||
dummynamespace.Name = ""
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
package models
|
||||
|
||||
import "code.vikunja.io/web"
|
||||
import (
|
||||
user2 "code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
)
|
||||
|
||||
// NamespaceUser represents a namespace <-> user relation
|
||||
type NamespaceUser struct {
|
||||
|
@ -75,7 +78,7 @@ func (nu *NamespaceUser) Create(a web.Auth) (err error) {
|
|||
}
|
||||
|
||||
// Check if the user exists
|
||||
user, err := GetUserByUsername(nu.Username)
|
||||
user, err := user2.GetUserByUsername(nu.Username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -117,7 +120,7 @@ func (nu *NamespaceUser) Create(a web.Auth) (err error) {
|
|||
func (nu *NamespaceUser) Delete() (err error) {
|
||||
|
||||
// Check if the user exists
|
||||
user, err := GetUserByUsername(nu.Username)
|
||||
user, err := user2.GetUserByUsername(nu.Username)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -213,7 +216,7 @@ func (nu *NamespaceUser) Update() (err error) {
|
|||
}
|
||||
|
||||
// Check if the user exists
|
||||
user, err := GetUserByUsername(nu.Username)
|
||||
user, err := user2.GetUserByUsername(nu.Username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/web"
|
||||
|
@ -48,7 +50,7 @@ func TestNamespaceUser_CanDoSomething(t *testing.T) {
|
|||
NamespaceID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 3},
|
||||
a: &user.User{ID: 3},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": true, "CanDelete": true, "CanUpdate": true},
|
||||
},
|
||||
|
@ -58,7 +60,7 @@ func TestNamespaceUser_CanDoSomething(t *testing.T) {
|
|||
NamespaceID: 300,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 3},
|
||||
a: &user.User{ID: 3},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false},
|
||||
},
|
||||
|
@ -68,13 +70,15 @@ func TestNamespaceUser_CanDoSomething(t *testing.T) {
|
|||
NamespaceID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 4},
|
||||
a: &user.User{ID: 4},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": false, "CanDelete": false, "CanUpdate": false},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
nu := &NamespaceUser{
|
||||
ID: tt.fields.ID,
|
||||
UserID: tt.fields.UserID,
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
"reflect"
|
||||
|
@ -56,7 +58,7 @@ func TestNamespaceUser_Create(t *testing.T) {
|
|||
name: "NamespaceUsers Create for duplicate",
|
||||
fields: fields{
|
||||
Username: "user1",
|
||||
NamespaceID: 2,
|
||||
NamespaceID: 3,
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrUserAlreadyHasNamespaceAccess,
|
||||
|
@ -87,7 +89,7 @@ func TestNamespaceUser_Create(t *testing.T) {
|
|||
NamespaceID: 2,
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrUserDoesNotExist,
|
||||
errType: user.IsErrUserDoesNotExist,
|
||||
},
|
||||
{
|
||||
name: "NamespaceUsers Create with the owner as shared user",
|
||||
|
@ -101,6 +103,8 @@ func TestNamespaceUser_Create(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
un := &NamespaceUser{
|
||||
ID: tt.fields.ID,
|
||||
Username: tt.fields.Username,
|
||||
|
@ -152,11 +156,11 @@ func TestNamespaceUser_ReadAll(t *testing.T) {
|
|||
NamespaceID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 3},
|
||||
a: &user.User{ID: 3},
|
||||
},
|
||||
want: []*UserWithRight{
|
||||
{
|
||||
User: User{
|
||||
User: user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -166,7 +170,7 @@ func TestNamespaceUser_ReadAll(t *testing.T) {
|
|||
Right: RightRead,
|
||||
},
|
||||
{
|
||||
User: User{
|
||||
User: user.User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -182,7 +186,7 @@ func TestNamespaceUser_ReadAll(t *testing.T) {
|
|||
NamespaceID: 3,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 4},
|
||||
a: &user.User{ID: 4},
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrNeedToHaveNamespaceReadAccess,
|
||||
|
@ -190,6 +194,8 @@ func TestNamespaceUser_ReadAll(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
un := &NamespaceUser{
|
||||
ID: tt.fields.ID,
|
||||
UserID: tt.fields.UserID,
|
||||
|
@ -269,6 +275,8 @@ func TestNamespaceUser_Update(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
nu := &NamespaceUser{
|
||||
ID: tt.fields.ID,
|
||||
Username: tt.fields.Username,
|
||||
|
@ -314,7 +322,7 @@ func TestNamespaceUser_Delete(t *testing.T) {
|
|||
NamespaceID: 2,
|
||||
},
|
||||
wantErr: true,
|
||||
errType: IsErrUserDoesNotExist,
|
||||
errType: user.IsErrUserDoesNotExist,
|
||||
},
|
||||
{
|
||||
name: "Try deleting a user which does not has access but exists",
|
||||
|
@ -335,6 +343,8 @@ func TestNamespaceUser_Delete(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
nu := &NamespaceUser{
|
||||
ID: tt.fields.ID,
|
||||
Username: tt.fields.Username,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
)
|
||||
|
||||
|
@ -38,8 +39,8 @@ func (TaskAssginee) TableName() string {
|
|||
|
||||
// TaskAssigneeWithUser is a helper type to deal with user joins
|
||||
type TaskAssigneeWithUser struct {
|
||||
TaskID int64
|
||||
User `xorm:"extends"`
|
||||
TaskID int64
|
||||
user.User `xorm:"extends"`
|
||||
}
|
||||
|
||||
func getRawTaskAssigneesForTasks(taskIDs []int64) (taskAssignees []*TaskAssigneeWithUser, err error) {
|
||||
|
@ -53,7 +54,7 @@ func getRawTaskAssigneesForTasks(taskIDs []int64) (taskAssignees []*TaskAssignee
|
|||
}
|
||||
|
||||
// Create or update a bunch of task assignees
|
||||
func (t *Task) updateTaskAssignees(assignees []*User) (err error) {
|
||||
func (t *Task) updateTaskAssignees(assignees []*user.User) (err error) {
|
||||
|
||||
// Load the current assignees
|
||||
currentAssignees, err := getRawTaskAssigneesForTasks([]int64{t.ID})
|
||||
|
@ -61,7 +62,7 @@ func (t *Task) updateTaskAssignees(assignees []*User) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
t.Assignees = make([]*User, 0, len(currentAssignees))
|
||||
t.Assignees = make([]*user.User, 0, len(currentAssignees))
|
||||
for _, assignee := range currentAssignees {
|
||||
t.Assignees = append(t.Assignees, &assignee.User)
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ func (t *Task) updateTaskAssignees(assignees []*User) (err error) {
|
|||
}
|
||||
|
||||
// Make a hashmap of the new assignees for easier comparison
|
||||
newAssignees := make(map[int64]*User, len(assignees))
|
||||
newAssignees := make(map[int64]*user.User, len(assignees))
|
||||
for _, newAssignee := range assignees {
|
||||
newAssignees[newAssignee.ID] = newAssignee
|
||||
}
|
||||
|
@ -88,7 +89,7 @@ func (t *Task) updateTaskAssignees(assignees []*User) (err error) {
|
|||
// Get old assignees to delete
|
||||
var found bool
|
||||
var assigneesToDelete []int64
|
||||
oldAssignees := make(map[int64]*User, len(t.Assignees))
|
||||
oldAssignees := make(map[int64]*user.User, len(t.Assignees))
|
||||
for _, oldAssignee := range t.Assignees {
|
||||
found = false
|
||||
if newAssignees[oldAssignee.ID] != nil {
|
||||
|
@ -142,7 +143,7 @@ func (t *Task) updateTaskAssignees(assignees []*User) (err error) {
|
|||
}
|
||||
|
||||
// Small helper functions to set the new assignees in various places
|
||||
func (t *Task) setTaskAssignees(assignees []*User) {
|
||||
func (t *Task) setTaskAssignees(assignees []*user.User) {
|
||||
if len(assignees) == 0 {
|
||||
t.Assignees = nil
|
||||
return
|
||||
|
@ -200,7 +201,7 @@ func (la *TaskAssginee) Create(a web.Auth) (err error) {
|
|||
|
||||
func (t *Task) addNewAssigneeByID(newAssigneeID int64, list *List) (err error) {
|
||||
// Check if the user exists and has access to the list
|
||||
newAssignee, err := GetUserByID(newAssigneeID)
|
||||
newAssignee, err := user.GetUserByID(newAssigneeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -252,7 +253,7 @@ func (la *TaskAssginee) ReadAll(a web.Auth, search string, page int, perPage int
|
|||
return nil, 0, 0, ErrGenericForbidden{}
|
||||
}
|
||||
|
||||
var taskAssignees []*User
|
||||
var taskAssignees []*user.User
|
||||
err = x.Table("task_assignees").
|
||||
Select("users.*").
|
||||
Join("INNER", "users", "task_assignees.user_id = users.id").
|
||||
|
@ -267,15 +268,15 @@ func (la *TaskAssginee) ReadAll(a web.Auth, search string, page int, perPage int
|
|||
Select("users.*").
|
||||
Join("INNER", "users", "task_assignees.user_id = users.id").
|
||||
Where("task_id = ? AND users.username LIKE ?", la.TaskID, "%"+search+"%").
|
||||
Count(&User{})
|
||||
Count(&user.User{})
|
||||
return taskAssignees, len(taskAssignees), numberOfTotalItems, err
|
||||
}
|
||||
|
||||
// BulkAssignees is a helper struct used to update multiple assignees at once.
|
||||
type BulkAssignees struct {
|
||||
// A list with all assignees
|
||||
Assignees []*User `json:"assignees"`
|
||||
TaskID int64 `json:"-" param:"listtask"`
|
||||
Assignees []*user.User `json:"assignees"`
|
||||
TaskID int64 `json:"-" param:"listtask"`
|
||||
|
||||
web.CRUDable `json:"-"`
|
||||
web.Rights `json:"-"`
|
||||
|
|
|
@ -18,6 +18,7 @@ package models
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"io"
|
||||
"time"
|
||||
|
@ -29,8 +30,8 @@ type TaskAttachment struct {
|
|||
TaskID int64 `xorm:"int(11) not null" json:"task_id" param:"task"`
|
||||
FileID int64 `xorm:"int(11) not null" json:"-"`
|
||||
|
||||
CreatedByID int64 `xorm:"int(11) not null" json:"-"`
|
||||
CreatedBy *User `xorm:"-" json:"created_by"`
|
||||
CreatedByID int64 `xorm:"int(11) not null" json:"-"`
|
||||
CreatedBy *user.User `xorm:"-" json:"created_by"`
|
||||
|
||||
File *files.File `xorm:"-" json:"file"`
|
||||
|
||||
|
@ -132,7 +133,7 @@ func (ta *TaskAttachment) ReadAll(a web.Auth, search string, page int, perPage i
|
|||
return nil, 0, 0, err
|
||||
}
|
||||
|
||||
us := make(map[int64]*User)
|
||||
us := make(map[int64]*user.User)
|
||||
err = x.In("id", userIDs).Find(&us)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
|
|
|
@ -20,6 +20,7 @@ package models
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -95,7 +96,7 @@ func TestTaskAttachment_NewAttachment(t *testing.T) {
|
|||
tf := &testfile{
|
||||
content: []byte("testingstuff"),
|
||||
}
|
||||
testuser := &User{ID: 1}
|
||||
testuser := &user.User{ID: 1}
|
||||
|
||||
err := ta.NewAttachment(tf, "testfile", 100, testuser)
|
||||
assert.NoError(t, err)
|
||||
|
@ -119,7 +120,7 @@ func TestTaskAttachment_NewAttachment(t *testing.T) {
|
|||
func TestTaskAttachment_ReadAll(t *testing.T) {
|
||||
files.InitTestFileFixtures(t)
|
||||
ta := &TaskAttachment{TaskID: 1}
|
||||
as, _, _, err := ta.ReadAll(&User{ID: 1}, "", 0, 50)
|
||||
as, _, _, err := ta.ReadAll(&user.User{ID: 1}, "", 0, 50)
|
||||
attachments, _ := as.([]*TaskAttachment)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, attachments, 3)
|
||||
|
@ -152,7 +153,7 @@ func TestTaskAttachment_Delete(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTaskAttachment_Rights(t *testing.T) {
|
||||
u := &User{ID: 1}
|
||||
u := &user.User{ID: 1}
|
||||
t.Run("Can Read", func(t *testing.T) {
|
||||
t.Run("Allowed", func(t *testing.T) {
|
||||
ta := &TaskAttachment{TaskID: 1}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"time"
|
||||
)
|
||||
|
@ -108,7 +109,7 @@ func (tf *TaskCollection) ReadAll(a web.Auth, search string, page int, perPage i
|
|||
// If the list ID is not set, we get all tasks for the user.
|
||||
// This allows to use this function in Task.ReadAll with a possibility to deprecate the latter at some point.
|
||||
if tf.ListID == 0 {
|
||||
tf.Lists, _, _, err = getRawListsForUser("", &User{ID: a.GetID()}, -1, 0)
|
||||
tf.Lists, _, _, err = getRawListsForUser("", &user.User{ID: a.GetID()}, -1, 0)
|
||||
if err != nil {
|
||||
return nil, 0, 0, err
|
||||
}
|
||||
|
|
|
@ -19,30 +19,28 @@ package models
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTaskCollection_ReadAll(t *testing.T) {
|
||||
assert.NoError(t, db.LoadFixtures())
|
||||
|
||||
// Dummy users
|
||||
user1 := &User{
|
||||
user1 := &user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808", // hash for ""
|
||||
}
|
||||
user2 := &User{
|
||||
user2 := &user.User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f", // hash for ""
|
||||
}
|
||||
user6 := &User{
|
||||
user6 := &user.User{
|
||||
ID: 6,
|
||||
Username: "user6",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -463,7 +461,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
CreatedByID: 1,
|
||||
CreatedBy: user1,
|
||||
ListID: 1,
|
||||
Assignees: []*User{
|
||||
Assignees: []*user.User{
|
||||
user1,
|
||||
user2,
|
||||
},
|
||||
|
@ -538,7 +536,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
fields: fields{},
|
||||
args: args{
|
||||
search: "",
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
page: 0,
|
||||
},
|
||||
want: []*Task{
|
||||
|
@ -585,7 +583,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
},
|
||||
args: args{
|
||||
search: "",
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
page: 0,
|
||||
},
|
||||
want: []*Task{
|
||||
|
@ -631,7 +629,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
},
|
||||
args: args{
|
||||
search: "",
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
page: 0,
|
||||
},
|
||||
want: []*Task{
|
||||
|
@ -648,7 +646,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
},
|
||||
args: args{
|
||||
search: "",
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
page: 0,
|
||||
},
|
||||
want: []*Task{
|
||||
|
@ -664,7 +662,7 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
},
|
||||
args: args{
|
||||
search: "",
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
page: 0,
|
||||
},
|
||||
want: []*Task{
|
||||
|
@ -677,6 +675,8 @@ func TestTaskCollection_ReadAll(t *testing.T) {
|
|||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
lt := &TaskCollection{
|
||||
ListID: tt.fields.ListID,
|
||||
StartDateSortUnix: tt.fields.StartDateSortUnix,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
)
|
||||
|
||||
|
@ -83,7 +84,7 @@ type TaskRelation struct {
|
|||
|
||||
CreatedByID int64 `xorm:"int(11) not null" json:"-"`
|
||||
// The user who created this relation
|
||||
CreatedBy *User `xorm:"-" json:"created_by"`
|
||||
CreatedBy *user.User `xorm:"-" json:"created_by"`
|
||||
|
||||
// A unix timestamp when this label was created. You cannot change this value.
|
||||
Created int64 `xorm:"created not null" json:"created"`
|
||||
|
|
|
@ -18,45 +18,55 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTaskRelation_Create(t *testing.T) {
|
||||
t.Run("Normal", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 2,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
err := rel.Create(&User{ID: 1})
|
||||
err := rel.Create(&user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("Two Tasks In Different Lists", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 13,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
err := rel.Create(&User{ID: 1})
|
||||
err := rel.Create(&user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("Already Existing", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 29,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
err := rel.Create(&User{ID: 1})
|
||||
err := rel.Create(&user.User{ID: 1})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrRelationAlreadyExists(err))
|
||||
})
|
||||
t.Run("Same Task", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 1,
|
||||
}
|
||||
err := rel.Create(&User{ID: 1})
|
||||
err := rel.Create(&user.User{ID: 1})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrRelationTasksCannotBeTheSame(err))
|
||||
})
|
||||
|
@ -64,6 +74,8 @@ func TestTaskRelation_Create(t *testing.T) {
|
|||
|
||||
func TestTaskRelation_Delete(t *testing.T) {
|
||||
t.Run("Normal", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 29,
|
||||
|
@ -73,6 +85,8 @@ func TestTaskRelation_Delete(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("Not existing", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 9999,
|
||||
OtherTaskID: 3,
|
||||
|
@ -86,73 +100,87 @@ func TestTaskRelation_Delete(t *testing.T) {
|
|||
|
||||
func TestTaskRelation_CanCreate(t *testing.T) {
|
||||
t.Run("Normal", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 2,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
can, err := rel.CanCreate(&User{ID: 1})
|
||||
can, err := rel.CanCreate(&user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, can)
|
||||
})
|
||||
t.Run("Two tasks on different lists", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 13,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
can, err := rel.CanCreate(&User{ID: 1})
|
||||
can, err := rel.CanCreate(&user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, can)
|
||||
})
|
||||
t.Run("No update rights on base task", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 14,
|
||||
OtherTaskID: 1,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
can, err := rel.CanCreate(&User{ID: 1})
|
||||
can, err := rel.CanCreate(&user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, can)
|
||||
})
|
||||
t.Run("No update rights on base task, but read rights", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 15,
|
||||
OtherTaskID: 1,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
can, err := rel.CanCreate(&User{ID: 1})
|
||||
can, err := rel.CanCreate(&user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, can)
|
||||
})
|
||||
t.Run("No read rights on other task", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 14,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
can, err := rel.CanCreate(&User{ID: 1})
|
||||
can, err := rel.CanCreate(&user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, can)
|
||||
})
|
||||
t.Run("Nonexisting base task", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 999999,
|
||||
OtherTaskID: 1,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
can, err := rel.CanCreate(&User{ID: 1})
|
||||
can, err := rel.CanCreate(&user.User{ID: 1})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTaskDoesNotExist(err))
|
||||
assert.False(t, can)
|
||||
})
|
||||
t.Run("Nonexisting other task", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
rel := TaskRelation{
|
||||
TaskID: 1,
|
||||
OtherTaskID: 999999,
|
||||
RelationKind: RelationKindSubtask,
|
||||
}
|
||||
can, err := rel.CanCreate(&User{ID: 1})
|
||||
can, err := rel.CanCreate(&user.User{ID: 1})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTaskDoesNotExist(err))
|
||||
assert.False(t, can)
|
||||
|
|
|
@ -19,6 +19,7 @@ package models
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/files"
|
||||
"code.vikunja.io/api/pkg/metrics"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/imdario/mergo"
|
||||
|
@ -55,7 +56,7 @@ type Task struct {
|
|||
// When this task ends.
|
||||
EndDateUnix int64 `xorm:"int(11) INDEX null" json:"endDate" query:"-"`
|
||||
// An array of users who are assigned to this task
|
||||
Assignees []*User `xorm:"-" json:"assignees"`
|
||||
Assignees []*user.User `xorm:"-" json:"assignees"`
|
||||
// An array of labels which are associated with this task.
|
||||
Labels []*Label `xorm:"-" json:"labels"`
|
||||
// The task color in hex
|
||||
|
@ -87,7 +88,7 @@ type Task struct {
|
|||
Updated int64 `xorm:"updated not null" json:"updated"`
|
||||
|
||||
// The user who initially created the task.
|
||||
CreatedBy *User `xorm:"-" json:"createdBy" valid:"-"`
|
||||
CreatedBy *user.User `xorm:"-" json:"createdBy" valid:"-"`
|
||||
|
||||
web.CRUDable `xorm:"-" json:"-"`
|
||||
web.Rights `xorm:"-" json:"-"`
|
||||
|
@ -365,7 +366,7 @@ func addMoreInfoToTasks(taskMap map[int64]*Task) (tasks []*Task, err error) {
|
|||
|
||||
// Get all users of a task
|
||||
// aka the ones who created a task
|
||||
users := make(map[int64]*User)
|
||||
users := make(map[int64]*user.User)
|
||||
err = x.In("id", userIDs).Find(&users)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -487,7 +488,7 @@ func (t *Task) Create(a web.Auth) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
u, err := GetUserByID(a.GetID())
|
||||
u, err := user.GetUserByID(a.GetID())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTask_Create(t *testing.T) {
|
||||
user := &User{
|
||||
usr := &user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Email: "user1@example.com",
|
||||
|
@ -31,13 +33,13 @@ func TestTask_Create(t *testing.T) {
|
|||
// We only test creating a task here, the rights are all well tested in the integration tests.
|
||||
|
||||
t.Run("normal", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
task := &Task{
|
||||
Text: "Lorem",
|
||||
Description: "Lorem Ipsum Dolor",
|
||||
ListID: 1,
|
||||
}
|
||||
err := task.Create(user)
|
||||
err := task.Create(usr)
|
||||
assert.NoError(t, err)
|
||||
// Assert getting a uid
|
||||
assert.NotEmpty(t, task.UID)
|
||||
|
@ -47,30 +49,30 @@ func TestTask_Create(t *testing.T) {
|
|||
|
||||
})
|
||||
t.Run("empty text", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
task := &Task{
|
||||
Text: "",
|
||||
Description: "Lorem Ipsum Dolor",
|
||||
ListID: 1,
|
||||
}
|
||||
err := task.Create(user)
|
||||
err := task.Create(usr)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrTaskCannotBeEmpty(err))
|
||||
})
|
||||
t.Run("nonexistant list", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
task := &Task{
|
||||
Text: "Test",
|
||||
Description: "Lorem Ipsum Dolor",
|
||||
ListID: 9999999,
|
||||
}
|
||||
err := task.Create(user)
|
||||
err := task.Create(usr)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrListDoesNotExist(err))
|
||||
})
|
||||
t.Run("noneixtant user", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
nUser := &User{ID: 99999999}
|
||||
db.LoadAndAssertFixtures(t)
|
||||
nUser := &user.User{ID: 99999999}
|
||||
task := &Task{
|
||||
Text: "Test",
|
||||
Description: "Lorem Ipsum Dolor",
|
||||
|
@ -78,13 +80,13 @@ func TestTask_Create(t *testing.T) {
|
|||
}
|
||||
err := task.Create(nUser)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, user.IsErrUserDoesNotExist(err))
|
||||
})
|
||||
}
|
||||
|
||||
func TestTask_Update(t *testing.T) {
|
||||
t.Run("normal", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
task := &Task{
|
||||
ID: 1,
|
||||
Text: "test10000",
|
||||
|
@ -95,7 +97,7 @@ func TestTask_Update(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("nonexistant task", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
task := &Task{
|
||||
ID: 9999999,
|
||||
Text: "test10000",
|
||||
|
@ -110,7 +112,7 @@ func TestTask_Update(t *testing.T) {
|
|||
|
||||
func TestTask_Delete(t *testing.T) {
|
||||
t.Run("normal", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
task := &Task{
|
||||
ID: 1,
|
||||
}
|
||||
|
@ -121,12 +123,14 @@ func TestTask_Delete(t *testing.T) {
|
|||
|
||||
func TestUpdateDone(t *testing.T) {
|
||||
t.Run("marking a task as done", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
oldTask := &Task{Done: false}
|
||||
newTask := &Task{Done: true}
|
||||
updateDone(oldTask, newTask)
|
||||
assert.NotEqual(t, int64(0), oldTask.DoneAtUnix)
|
||||
})
|
||||
t.Run("unmarking a task as done", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
oldTask := &Task{Done: true}
|
||||
newTask := &Task{Done: false}
|
||||
updateDone(oldTask, newTask)
|
||||
|
@ -136,14 +140,14 @@ func TestUpdateDone(t *testing.T) {
|
|||
|
||||
func TestTask_ReadOne(t *testing.T) {
|
||||
t.Run("default", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
task := &Task{ID: 1}
|
||||
err := task.ReadOne()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "task #1", task.Text)
|
||||
})
|
||||
t.Run("nonexisting", func(t *testing.T) {
|
||||
initFixtures(t)
|
||||
db.LoadAndAssertFixtures(t)
|
||||
task := &Task{ID: 99999}
|
||||
err := task.ReadOne()
|
||||
assert.Error(t, err)
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
|
||||
package models
|
||||
|
||||
import "code.vikunja.io/web"
|
||||
import (
|
||||
user2 "code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
)
|
||||
|
||||
// Create implements the create method to assign a user to a team
|
||||
// @Summary Add a user to a team
|
||||
|
@ -41,7 +44,7 @@ func (tm *TeamMember) Create(a web.Auth) (err error) {
|
|||
}
|
||||
|
||||
// Check if the user exists
|
||||
user, err := GetUserByUsername(tm.Username)
|
||||
user, err := user2.GetUserByUsername(tm.Username)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -84,7 +87,7 @@ func (tm *TeamMember) Delete() (err error) {
|
|||
}
|
||||
|
||||
// Find the numeric user id
|
||||
user, err := GetUserByUsername(tm.Username)
|
||||
user, err := user2.GetUserByUsername(tm.Username)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -17,11 +17,14 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTeamMember_Create(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
// Dummy team member
|
||||
dummyteammember := TeamMember{
|
||||
|
@ -30,7 +33,7 @@ func TestTeamMember_Create(t *testing.T) {
|
|||
}
|
||||
|
||||
// Doer
|
||||
doer, err := GetUserByID(1)
|
||||
doer, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Insert a new team member
|
||||
|
@ -71,7 +74,7 @@ func TestTeamMember_Create(t *testing.T) {
|
|||
dummyteammember.Username = "user9484"
|
||||
err = dummyteammember.Create(doer)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
assert.True(t, user.IsErrUserDoesNotExist(err))
|
||||
|
||||
// Try adding a user to a team which does not exist
|
||||
tm = TeamMember{TeamID: 94824, Username: "user1"}
|
||||
|
|
|
@ -18,6 +18,7 @@ package models
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/metrics"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
)
|
||||
|
||||
|
@ -32,7 +33,7 @@ type Team struct {
|
|||
CreatedByID int64 `xorm:"int(11) not null INDEX" json:"-"`
|
||||
|
||||
// The user who created this team.
|
||||
CreatedBy *User `xorm:"-" json:"createdBy"`
|
||||
CreatedBy *user.User `xorm:"-" json:"createdBy"`
|
||||
// An array of all members in this team.
|
||||
Members []*TeamUser `xorm:"-" json:"members"`
|
||||
|
||||
|
@ -53,7 +54,7 @@ func (Team) TableName() string {
|
|||
// AfterLoad gets the created by user object
|
||||
func (t *Team) AfterLoad() {
|
||||
// Get the owner
|
||||
t.CreatedBy, _ = GetUserByID(t.CreatedByID)
|
||||
t.CreatedBy, _ = user.GetUserByID(t.CreatedByID)
|
||||
|
||||
// Get all members
|
||||
x.Select("*").
|
||||
|
@ -90,7 +91,7 @@ func (TeamMember) TableName() string {
|
|||
|
||||
// TeamUser is the team member type
|
||||
type TeamUser struct {
|
||||
User `xorm:"extends"`
|
||||
user.User `xorm:"extends"`
|
||||
// Whether or not the member is an admin of the team. See the docs for more about what a team admin can do
|
||||
Admin bool `json:"admin"`
|
||||
}
|
||||
|
@ -181,7 +182,7 @@ func (t *Team) ReadAll(a web.Auth, search string, page int, perPage int) (result
|
|||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /teams [put]
|
||||
func (t *Team) Create(a web.Auth) (err error) {
|
||||
doer, err := getUserWithError(a)
|
||||
doer, err := user.GetFromAuth(a)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"testing"
|
||||
|
||||
"code.vikunja.io/web"
|
||||
|
@ -28,7 +30,7 @@ func TestTeam_CanDoSomething(t *testing.T) {
|
|||
Name string
|
||||
Description string
|
||||
CreatedByID int64
|
||||
CreatedBy *User
|
||||
CreatedBy *user.User
|
||||
Members []*TeamUser
|
||||
Created int64
|
||||
Updated int64
|
||||
|
@ -50,7 +52,7 @@ func TestTeam_CanDoSomething(t *testing.T) {
|
|||
ID: 1,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": true, "IsAdmin": true, "CanRead": true, "CanDelete": true, "CanUpdate": true},
|
||||
},
|
||||
|
@ -60,7 +62,7 @@ func TestTeam_CanDoSomething(t *testing.T) {
|
|||
ID: 300,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 1},
|
||||
a: &user.User{ID: 1},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": true, "IsAdmin": false, "CanRead": false, "CanDelete": false, "CanUpdate": false},
|
||||
},
|
||||
|
@ -70,13 +72,15 @@ func TestTeam_CanDoSomething(t *testing.T) {
|
|||
ID: 1,
|
||||
},
|
||||
args: args{
|
||||
a: &User{ID: 4},
|
||||
a: &user.User{ID: 4},
|
||||
},
|
||||
want: map[string]bool{"CanCreate": true, "IsAdmin": false, "CanRead": false, "CanDelete": false, "CanUpdate": false},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
tm := &Team{
|
||||
ID: tt.fields.ID,
|
||||
Name: tt.fields.Name,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
@ -30,7 +31,7 @@ func TestTeam_Create(t *testing.T) {
|
|||
}
|
||||
|
||||
// Doer
|
||||
doer, err := GetUserByID(1)
|
||||
doer, err := user.GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Insert it
|
||||
|
|
|
@ -17,78 +17,49 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
_ "code.vikunja.io/api/pkg/config" // To trigger its init() which initializes the config
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/mail"
|
||||
"fmt"
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/testfixtures.v2"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// SetupTests takes care of seting up the db, fixtures etc.
|
||||
// This is an extra function to be able to call the fixtures setup from the integration tests.
|
||||
func SetupTests(pathToRoot string) {
|
||||
func SetupTests() {
|
||||
var err error
|
||||
fixturesDir := filepath.Join(pathToRoot, "pkg", "models", "fixtures")
|
||||
if err = createTestEngine(fixturesDir); err != nil {
|
||||
log.Fatalf("Error creating test engine: %v\n", err)
|
||||
x, err = db.CreateTestEngine()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = x.Sync2(GetTables()...)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
err = db.InitTestFixtures(
|
||||
"files",
|
||||
"label_task",
|
||||
"labels",
|
||||
"link_sharing",
|
||||
"list",
|
||||
"namespaces",
|
||||
"task_assignees",
|
||||
"task_attachments",
|
||||
"task_relations",
|
||||
"task_reminders",
|
||||
"tasks",
|
||||
"team_list",
|
||||
"team_members",
|
||||
"team_namespaces",
|
||||
"teams",
|
||||
"users",
|
||||
"users_list",
|
||||
"users_namespace")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Start the pseudo mail queue
|
||||
mail.StartMailDaemon()
|
||||
|
||||
// Create test database
|
||||
if err = db.LoadFixtures(); err != nil {
|
||||
log.Fatalf("Error preparing test database: %v", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func createTestEngine(fixturesDir string) error {
|
||||
var err error
|
||||
var fixturesHelper testfixtures.Helper = &testfixtures.SQLite{}
|
||||
// If set, use the config we provided instead of normal
|
||||
if os.Getenv("VIKUNJA_TESTS_USE_CONFIG") == "1" {
|
||||
x, err = db.CreateTestEngine()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting test engine: %v", err)
|
||||
}
|
||||
|
||||
err = initSchema(x)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if config.DatabaseType.GetString() == "mysql" {
|
||||
fixturesHelper = &testfixtures.MySQL{}
|
||||
}
|
||||
} else {
|
||||
x, err = db.CreateTestEngine()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting test engine: %v", err)
|
||||
}
|
||||
|
||||
// Sync dat shit
|
||||
err = initSchema(x)
|
||||
if err != nil {
|
||||
return fmt.Errorf("sync database struct error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return db.InitFixtures(fixturesHelper, fixturesDir)
|
||||
}
|
||||
|
||||
func initSchema(tx *xorm.Engine) error {
|
||||
return tx.Sync2(GetTables()...)
|
||||
}
|
||||
|
||||
func initFixtures(t *testing.T) {
|
||||
// Init db fixtures
|
||||
err := db.LoadFixtures()
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
|
|
@ -1,40 +1,26 @@
|
|||
// Vikunja is a todo-list application to facilitate your life.
|
||||
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
|
||||
// Copyright 2018-2020 Vikunja and contriubtors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// This file is part of Vikunja.
|
||||
//
|
||||
// Vikunja is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// Vikunja is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package models
|
||||
|
||||
import "github.com/go-xorm/builder"
|
||||
|
||||
// ListUsers returns a list with all users, filtered by an optional searchstring
|
||||
func ListUsers(searchterm string) (users []User, err error) {
|
||||
|
||||
if searchterm == "" {
|
||||
err = x.Find(&users)
|
||||
} else {
|
||||
err = x.
|
||||
Where("username LIKE ?", "%"+searchterm+"%").
|
||||
Find(&users)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return []User{}, err
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/go-xorm/builder"
|
||||
)
|
||||
|
||||
// ListUIDs hold all kinds of user IDs from accounts who have somehow access to a list
|
||||
type ListUIDs struct {
|
||||
|
@ -47,7 +33,7 @@ type ListUIDs struct {
|
|||
}
|
||||
|
||||
// ListUsersFromList returns a list with all users who have access to a list, regardless of the method which gave them access
|
||||
func ListUsersFromList(l *List, search string) (users []*User, err error) {
|
||||
func ListUsersFromList(l *List, search string) (users []*user.User, err error) {
|
||||
|
||||
userids := []*ListUIDs{}
|
||||
|
|
@ -1,178 +0,0 @@
|
|||
// Vikunja is a todo-list application to facilitate your life.
|
||||
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateUser(t *testing.T) {
|
||||
// Create test database
|
||||
//assert.NoError(t, LoadFixtures())
|
||||
|
||||
// Get our doer
|
||||
doer, err := GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Our dummy user for testing
|
||||
dummyuser := &User{
|
||||
Username: "testuu",
|
||||
Password: "1234",
|
||||
Email: "noone@example.com",
|
||||
}
|
||||
|
||||
// Create a new user
|
||||
createdUser, err := CreateUser(dummyuser)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Create a second new user
|
||||
_, err = CreateUser(&User{Username: dummyuser.Username + "2", Email: dummyuser.Email + "m", Password: dummyuser.Password})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check if it fails to create the same user again
|
||||
_, err = CreateUser(dummyuser)
|
||||
assert.Error(t, err)
|
||||
|
||||
// Check if it fails to create a user with just the same username
|
||||
_, err = CreateUser(&User{Username: dummyuser.Username, Password: "12345", Email: "email@example.com"})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUsernameExists(err))
|
||||
|
||||
// Check if it fails to create one with the same email
|
||||
_, err = CreateUser(&User{Username: "noone", Password: "1234", Email: dummyuser.Email})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserEmailExists(err))
|
||||
|
||||
// Check if it fails to create a user without password and username
|
||||
_, err = CreateUser(&User{})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrNoUsernamePassword(err))
|
||||
|
||||
// Check if he exists
|
||||
theuser, err := GetUser(createdUser)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Get by his ID
|
||||
_, err = GetUserByID(theuser.ID)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Passing 0 as ID should return an error
|
||||
_, err = GetUserByID(0)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
|
||||
// Check the user credentials with an unverified email
|
||||
_, err = CheckUserCredentials(&UserLogin{"user5", "1234"})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrEmailNotConfirmed(err))
|
||||
|
||||
// Update everything and check again
|
||||
_, err = x.Cols("is_active").Where("true").Update(User{IsActive: true})
|
||||
assert.NoError(t, err)
|
||||
user, err := CheckUserCredentials(&UserLogin{"testuu", "1234"})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "testuu", user.Username)
|
||||
|
||||
// Check wrong password (should also fail)
|
||||
_, err = CheckUserCredentials(&UserLogin{"testuu", "12345"})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrWrongUsernameOrPassword(err))
|
||||
|
||||
// Check usercredentials for a nonexistent user (should fail)
|
||||
_, err = CheckUserCredentials(&UserLogin{"dfstestuu", "1234"})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrWrongUsernameOrPassword(err))
|
||||
|
||||
// Update the user
|
||||
uuser, err := UpdateUser(&User{ID: theuser.ID, Password: "444444"})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, theuser.Password, uuser.Password) // Password should not change
|
||||
assert.Equal(t, theuser.Username, uuser.Username) // Username should not change either
|
||||
|
||||
// Try updating one which does not exist
|
||||
_, err = UpdateUser(&User{ID: 99999, Username: "dg"})
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
|
||||
// Update a users password
|
||||
newpassword := "55555"
|
||||
err = UpdateUserPassword(theuser, newpassword)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check if it was changed
|
||||
_, err = CheckUserCredentials(&UserLogin{theuser.Username, newpassword})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check if the searchterm works
|
||||
all, err := ListUsers("test")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, len(all) > 0)
|
||||
|
||||
all, err = ListUsers("")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, len(all) > 0)
|
||||
|
||||
// Try updating the password of a nonexistent user (should fail)
|
||||
err = UpdateUserPassword(&User{ID: 9999}, newpassword)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrUserDoesNotExist(err))
|
||||
|
||||
// Delete it
|
||||
err = DeleteUserByID(theuser.ID, doer)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try deleting one with ID = 0
|
||||
err = DeleteUserByID(0, doer)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrIDCannotBeZero(err))
|
||||
}
|
||||
|
||||
func TestUserPasswordReset(t *testing.T) {
|
||||
// Request a new token
|
||||
tr := &PasswordTokenRequest{
|
||||
Email: "user1@example.com",
|
||||
}
|
||||
err := RequestUserPasswordResetToken(tr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Get the token / inside the user object
|
||||
userWithToken, err := GetUserByID(1)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try resetting it
|
||||
reset := &PasswordReset{
|
||||
Token: userWithToken.PasswordResetToken,
|
||||
}
|
||||
|
||||
// Try resetting it without a password
|
||||
reset.NewPassword = ""
|
||||
err = UserPasswordReset(reset)
|
||||
assert.True(t, IsErrNoUsernamePassword(err))
|
||||
|
||||
// Reset it
|
||||
reset.NewPassword = "1234"
|
||||
err = UserPasswordReset(reset)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Try resetting it with a wrong token
|
||||
reset.Token = utils.MakeRandomString(400)
|
||||
err = UserPasswordReset(reset)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrInvalidPasswordResetToken(err))
|
||||
}
|
|
@ -1,38 +1,51 @@
|
|||
// Copyright 2018-2020 Vikunja and contriubtors. All rights reserved.
|
||||
//
|
||||
// This file is part of Vikunja.
|
||||
//
|
||||
// Vikunja is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vikunja is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"gopkg.in/d4l3k/messagediff.v1"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestListUsersFromList(t *testing.T) {
|
||||
|
||||
err := db.LoadFixtures()
|
||||
assert.NoError(t, err)
|
||||
|
||||
testuser1 := &User{
|
||||
testuser1 := &user.User{
|
||||
ID: 1,
|
||||
Username: "user1",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "111d68d06e2d317b5a59c2c6c5bad808",
|
||||
}
|
||||
testuser2 := &User{
|
||||
testuser2 := &user.User{
|
||||
ID: 2,
|
||||
Username: "user2",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
AvatarURL: "ab53a2911ddf9b4817ac01ddcd3d975f",
|
||||
}
|
||||
testuser3 := &User{
|
||||
testuser3 := &user.User{
|
||||
ID: 3,
|
||||
Username: "user3",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
AvatarURL: "97d6d9441ff85fdc730e02a6068d267b",
|
||||
PasswordResetToken: "passwordresettesttoken",
|
||||
}
|
||||
testuser4 := &User{
|
||||
testuser4 := &user.User{
|
||||
ID: 4,
|
||||
Username: "user4",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -40,7 +53,7 @@ func TestListUsersFromList(t *testing.T) {
|
|||
AvatarURL: "7e65550957227bd38fe2d7fbc6fd2f7b",
|
||||
EmailConfirmToken: "tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael",
|
||||
}
|
||||
testuser5 := &User{
|
||||
testuser5 := &user.User{
|
||||
ID: 5,
|
||||
Username: "user5",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -48,56 +61,56 @@ func TestListUsersFromList(t *testing.T) {
|
|||
AvatarURL: "cfa35b8cd2ec278026357769582fa563",
|
||||
EmailConfirmToken: "tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael",
|
||||
}
|
||||
testuser6 := &User{
|
||||
testuser6 := &user.User{
|
||||
ID: 6,
|
||||
Username: "user6",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "3efbe51f864c6666bc27caf4c6ff90ed",
|
||||
}
|
||||
testuser7 := &User{
|
||||
testuser7 := &user.User{
|
||||
ID: 7,
|
||||
Username: "user7",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "e80a711d4de44c30054806ebbd488464",
|
||||
}
|
||||
testuser8 := &User{
|
||||
testuser8 := &user.User{
|
||||
ID: 8,
|
||||
Username: "user8",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "2b9b320416cd31020bb6844c3fadefd1",
|
||||
}
|
||||
testuser9 := &User{
|
||||
testuser9 := &user.User{
|
||||
ID: 9,
|
||||
Username: "user9",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "f784fdb21d26dd2c64f5135f35ec401f",
|
||||
}
|
||||
testuser10 := &User{
|
||||
testuser10 := &user.User{
|
||||
ID: 10,
|
||||
Username: "user10",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "fce8ff4ff56d75ad587d1bbaa5ef0563",
|
||||
}
|
||||
testuser11 := &User{
|
||||
testuser11 := &user.User{
|
||||
ID: 11,
|
||||
Username: "user11",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "ad6d67d0c4495e186010732a7d360028",
|
||||
}
|
||||
testuser12 := &User{
|
||||
testuser12 := &user.User{
|
||||
ID: 12,
|
||||
Username: "user12",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
IsActive: true,
|
||||
AvatarURL: "ef1debc1364806281c42eeedfdeb943b",
|
||||
}
|
||||
testuser13 := &User{
|
||||
testuser13 := &user.User{
|
||||
ID: 13,
|
||||
Username: "user13",
|
||||
Password: "$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.",
|
||||
|
@ -112,19 +125,19 @@ func TestListUsersFromList(t *testing.T) {
|
|||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantUsers []*User
|
||||
wantUsers []*user.User
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Check owner only",
|
||||
args: args{l: &List{ID: 18, OwnerID: 7}},
|
||||
wantUsers: []*User{testuser7},
|
||||
wantUsers: []*user.User{testuser7},
|
||||
},
|
||||
{
|
||||
// This list has another different user shared for each possible method
|
||||
name: "Check with owner and other users",
|
||||
args: args{l: &List{ID: 19, OwnerID: 7}},
|
||||
wantUsers: []*User{
|
||||
wantUsers: []*user.User{
|
||||
testuser1, // Shared Via Team readonly
|
||||
testuser2, // Shared Via Team write
|
||||
testuser3, // Shared Via Team admin
|
||||
|
@ -147,6 +160,8 @@ func TestListUsersFromList(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
|
||||
gotUsers, err := ListUsersFromList(tt.args.l, tt.args.search)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ListUsersFromList() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
|
|
@ -19,12 +19,13 @@ package migration
|
|||
import (
|
||||
"bytes"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// InsertFromStructure takes a fully nested Vikunja data structure and a user and then creates everything for this user
|
||||
// (Namespaces, tasks, etc. Even attachments and relations.)
|
||||
func InsertFromStructure(str []*models.NamespaceWithLists, user *models.User) (err error) {
|
||||
func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err error) {
|
||||
|
||||
// Create all namespaces
|
||||
for _, n := range str {
|
||||
|
|
|
@ -19,6 +19,7 @@ package handler
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/modules/migration"
|
||||
user2 "code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -53,7 +54,7 @@ func (mw *MigrationWeb) Migrate(c echo.Context) error {
|
|||
ms := mw.MigrationStruct()
|
||||
|
||||
// Get the user from context
|
||||
user, err := models.GetCurrentUser(c)
|
||||
user, err := user2.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ func (mw *MigrationWeb) Migrate(c echo.Context) error {
|
|||
func (mw *MigrationWeb) Status(c echo.Context) error {
|
||||
ms := mw.MigrationStruct()
|
||||
|
||||
user, err := models.GetCurrentUser(c)
|
||||
user, err := user2.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
package migration
|
||||
|
||||
import "code.vikunja.io/api/pkg/models"
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Status represents this migration status
|
||||
type Status struct {
|
||||
|
@ -32,7 +34,7 @@ func (s *Status) TableName() string {
|
|||
}
|
||||
|
||||
// SetMigrationStatus sets the migration status for a user
|
||||
func SetMigrationStatus(m Migrator, u *models.User) (err error) {
|
||||
func SetMigrationStatus(m Migrator, u *user.User) (err error) {
|
||||
status := &Status{
|
||||
UserID: u.ID,
|
||||
MigratorName: m.Name(),
|
||||
|
@ -42,7 +44,7 @@ func SetMigrationStatus(m Migrator, u *models.User) (err error) {
|
|||
}
|
||||
|
||||
// GetMigrationStatus returns the migration status for a migration and a user
|
||||
func GetMigrationStatus(m Migrator, u *models.User) (status *Status, err error) {
|
||||
func GetMigrationStatus(m Migrator, u *user.User) (status *Status, err error) {
|
||||
status = &Status{}
|
||||
_, err = x.Where("user_id = ? and migrator_name = ?", u.ID, m.Name()).Desc("id").Get(status)
|
||||
return
|
||||
|
|
|
@ -17,13 +17,15 @@
|
|||
|
||||
package migration
|
||||
|
||||
import "code.vikunja.io/api/pkg/models"
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
)
|
||||
|
||||
// Migrator is the basic migrator interface which is shared among all migrators
|
||||
type Migrator interface {
|
||||
// Migrate is the interface used to migrate a user's tasks from another platform to vikunja.
|
||||
// The user object is the user who's tasks will be migrated.
|
||||
Migrate(user *models.User) error
|
||||
Migrate(user *user.User) error
|
||||
// AuthURL returns a url for clients to authenticate against.
|
||||
// The use case for this are Oauth flows, where the server token should remain hidden and not
|
||||
// known to the frontend.
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/modules/migration"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -341,7 +342,7 @@ func makeAuthGetRequest(token *wunderlistAuthToken, urlPart string, v interface{
|
|||
// @Success 200 {object} models.Message "A message telling you everything was migrated successfully."
|
||||
// @Failure 500 {object} models.Message "Internal server error"
|
||||
// @Router /migration/wunderlist/migrate [post]
|
||||
func (w *Migration) Migrate(user *models.User) (err error) {
|
||||
func (w *Migration) Migrate(user *user.User) (err error) {
|
||||
|
||||
log.Debugf("[Wunderlist migration] Starting wunderlist migration for user %d", user.ID)
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ package v1
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/labstack/echo/v4"
|
||||
|
@ -34,7 +35,7 @@ const (
|
|||
)
|
||||
|
||||
// NewUserJWTAuthtoken generates and signes a new jwt token for a user. This is a global function to be able to call it from integration tests.
|
||||
func NewUserJWTAuthtoken(user *models.User) (token string, err error) {
|
||||
func NewUserJWTAuthtoken(user *user.User) (token string, err error) {
|
||||
t := jwt.New(jwt.SigningMethodHS256)
|
||||
|
||||
// Set claims
|
||||
|
@ -78,7 +79,7 @@ func GetAuthFromClaims(c echo.Context) (a web.Auth, err error) {
|
|||
return models.GetLinkShareFromClaims(claims)
|
||||
}
|
||||
if typ == AuthTypeUser {
|
||||
return models.GetUserFromClaims(claims)
|
||||
return user.GetUserFromClaims(claims)
|
||||
}
|
||||
return nil, echo.NewHTTPError(http.StatusBadRequest, models.Message{Message: "Invalid JWT token."})
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package v1
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -46,7 +47,7 @@ func GetListsByNamespaceID(c echo.Context) error {
|
|||
}
|
||||
|
||||
// Get the lists
|
||||
doer, err := models.GetCurrentUser(c)
|
||||
doer, err := user.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
@ -73,7 +74,7 @@ func getNamespace(c echo.Context) (namespace *models.Namespace, err error) {
|
|||
}
|
||||
|
||||
// Check if the user has acces to that namespace
|
||||
user, err := models.GetCurrentUser(c)
|
||||
user, err := user.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package v1
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
user2 "code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/labstack/echo/v4"
|
||||
|
@ -41,13 +42,13 @@ type Token struct {
|
|||
// @Failure 403 {object} models.Message "Invalid username or password."
|
||||
// @Router /login [post]
|
||||
func Login(c echo.Context) error {
|
||||
u := models.UserLogin{}
|
||||
u := user2.Login{}
|
||||
if err := c.Bind(&u); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, models.Message{"Please provide a username and password."})
|
||||
}
|
||||
|
||||
// Check user
|
||||
user, err := models.CheckUserCredentials(&u)
|
||||
user, err := user2.CheckUserCredentials(&u)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ func RenewToken(c echo.Context) error {
|
|||
return echo.ErrBadRequest
|
||||
}
|
||||
|
||||
user, err := models.GetUserFromClaims(claims)
|
||||
user, err := user2.GetUserFromClaims(claims)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package v1
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
user2 "code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -45,7 +46,7 @@ func UploadTaskAttachment(c echo.Context) error {
|
|||
}
|
||||
|
||||
// Rights check
|
||||
user, err := models.GetCurrentUser(c)
|
||||
user, err := user2.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
@ -114,7 +115,7 @@ func GetTaskAttachment(c echo.Context) error {
|
|||
}
|
||||
|
||||
// Rights check
|
||||
user, err := models.GetCurrentUser(c)
|
||||
user, err := user2.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package v1
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -40,13 +41,20 @@ func RegisterUser(c echo.Context) error {
|
|||
return echo.ErrNotFound
|
||||
}
|
||||
// Check for Request Content
|
||||
var datUser *models.APIUserPassword
|
||||
var datUser *user.APIUserPassword
|
||||
if err := c.Bind(&datUser); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, models.Message{"No or invalid user model provided."})
|
||||
}
|
||||
|
||||
// Insert the user
|
||||
newUser, err := models.CreateUser(datUser.APIFormat())
|
||||
newUser, err := user.CreateUser(datUser.APIFormat())
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
// Add its namespace
|
||||
newN := &models.Namespace{Name: newUser.Username, Description: newUser.Username + "'s namespace.", Owner: newUser}
|
||||
err = newN.Create(newUser)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package v1
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -36,12 +37,12 @@ import (
|
|||
// @Router /user/confirm [post]
|
||||
func UserConfirmEmail(c echo.Context) error {
|
||||
// Check for Request Content
|
||||
var emailConfirm models.EmailConfirm
|
||||
var emailConfirm user.EmailConfirm
|
||||
if err := c.Bind(&emailConfirm); err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "No token provided.")
|
||||
}
|
||||
|
||||
err := models.UserEmailConfirm(&emailConfirm)
|
||||
err := user.ConfirmEmail(&emailConfirm)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
// Vikunja is a todo-list application to facilitate your life.
|
||||
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// UserDelete is the handler to delete a user
|
||||
func UserDelete(c echo.Context) error {
|
||||
|
||||
// TODO: only allow users to allow itself
|
||||
|
||||
id := c.Param("id")
|
||||
|
||||
// Make int
|
||||
userID, err := strconv.ParseInt(id, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, models.Message{"User ID is invalid."})
|
||||
}
|
||||
|
||||
// Check if the user exists
|
||||
_, err = models.GetUserByID(userID)
|
||||
|
||||
if err != nil {
|
||||
if models.IsErrUserDoesNotExist(err) {
|
||||
return c.JSON(http.StatusNotFound, models.Message{"The user does not exist."})
|
||||
}
|
||||
return c.JSON(http.StatusInternalServerError, models.Message{"Could not get user."})
|
||||
}
|
||||
|
||||
// Get the doer options
|
||||
doer, err := models.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete it
|
||||
err = models.DeleteUserByID(userID, doer)
|
||||
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, models.Message{"success"})
|
||||
}
|
|
@ -18,6 +18,7 @@ package v1
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -38,7 +39,7 @@ import (
|
|||
// @Router /users [get]
|
||||
func UserList(c echo.Context) error {
|
||||
s := c.QueryParam("s")
|
||||
users, err := models.ListUsers(s)
|
||||
users, err := user.ListUsers(s)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
@ -72,7 +73,7 @@ func ListUsersForList(c echo.Context) error {
|
|||
}
|
||||
|
||||
list := models.List{ID: listID}
|
||||
currentUser, err := models.GetCurrentUser(c)
|
||||
currentUser, err := user.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package v1
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -36,12 +37,12 @@ import (
|
|||
// @Router /user/password/reset [post]
|
||||
func UserResetPassword(c echo.Context) error {
|
||||
// Check for Request Content
|
||||
var pwReset models.PasswordReset
|
||||
var pwReset user.PasswordReset
|
||||
if err := c.Bind(&pwReset); err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "No password provided.")
|
||||
}
|
||||
|
||||
err := models.UserPasswordReset(&pwReset)
|
||||
err := user.ResetPassword(&pwReset)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
@ -62,7 +63,7 @@ func UserResetPassword(c echo.Context) error {
|
|||
// @Router /user/password/token [post]
|
||||
func UserRequestResetPasswordToken(c echo.Context) error {
|
||||
// Check for Request Content
|
||||
var pwTokenReset models.PasswordTokenRequest
|
||||
var pwTokenReset user.PasswordTokenRequest
|
||||
if err := c.Bind(&pwTokenReset); err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "No username provided.")
|
||||
}
|
||||
|
@ -71,7 +72,7 @@ func UserRequestResetPasswordToken(c echo.Context) error {
|
|||
return echo.NewHTTPError(http.StatusBadRequest, err)
|
||||
}
|
||||
|
||||
err := models.RequestUserPasswordResetToken(&pwTokenReset)
|
||||
err := user.RequestUserPasswordResetToken(&pwTokenReset)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
user2 "code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -35,12 +35,12 @@ import (
|
|||
// @Failure 500 {object} models.Message "Internal server error."
|
||||
// @Router /user [get]
|
||||
func UserShow(c echo.Context) error {
|
||||
userInfos, err := models.GetCurrentUser(c)
|
||||
userInfos, err := user2.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Error getting current user.")
|
||||
}
|
||||
|
||||
user, err := models.GetUserByID(userInfos.ID)
|
||||
user, err := user2.GetUserByID(userInfos.ID)
|
||||
if err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package v1
|
|||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/labstack/echo/v4"
|
||||
"net/http"
|
||||
|
@ -44,7 +45,7 @@ type UserPassword struct {
|
|||
// @Router /user/password [post]
|
||||
func UserChangePassword(c echo.Context) error {
|
||||
// Check if the user is itself
|
||||
doer, err := models.GetCurrentUser(c)
|
||||
doer, err := user.GetCurrentUser(c)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Error getting current user.")
|
||||
}
|
||||
|
@ -56,16 +57,16 @@ func UserChangePassword(c echo.Context) error {
|
|||
}
|
||||
|
||||
if newPW.OldPassword == "" {
|
||||
return handler.HandleHTTPError(models.ErrEmptyOldPassword{}, c)
|
||||
return handler.HandleHTTPError(user.ErrEmptyOldPassword{}, c)
|
||||
}
|
||||
|
||||
// Check the current password
|
||||
if _, err = models.CheckUserCredentials(&models.UserLogin{Username: doer.Username, Password: newPW.OldPassword}); err != nil {
|
||||
if _, err = user.CheckUserCredentials(&user.Login{Username: doer.Username, Password: newPW.OldPassword}); err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
// Update the password
|
||||
if err = models.UpdateUserPassword(doer, newPW.NewPassword); err != nil {
|
||||
if err = user.UpdateUserPassword(doer, newPW.NewPassword); err != nil {
|
||||
return handler.HandleHTTPError(err, c)
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"bytes"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web/handler"
|
||||
"fmt"
|
||||
"github.com/labstack/echo/v4"
|
||||
|
@ -31,10 +32,10 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func getBasicAuthUserFromContext(c echo.Context) (user models.User, err error) {
|
||||
u, is := c.Get("userBasicAuth").(models.User)
|
||||
func getBasicAuthUserFromContext(c echo.Context) (user.User, error) {
|
||||
u, is := c.Get("userBasicAuth").(user.User)
|
||||
if !is {
|
||||
return models.User{}, fmt.Errorf("user is not user element, is %s", reflect.TypeOf(c.Get("userBasicAuth")))
|
||||
return user.User{}, fmt.Errorf("user is not user element, is %s", reflect.TypeOf(c.Get("userBasicAuth")))
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package caldav
|
|||
import (
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
user2 "code.vikunja.io/api/pkg/user"
|
||||
"github.com/samedi/caldav-go/data"
|
||||
"github.com/samedi/caldav-go/errs"
|
||||
"strconv"
|
||||
|
@ -39,7 +40,7 @@ type VikunjaCaldavListStorage struct {
|
|||
// Used when handling a single task, like updating
|
||||
task *models.Task
|
||||
// The current user
|
||||
user *models.User
|
||||
user *user2.User
|
||||
isPrincipal bool
|
||||
isEntry bool // Entry level handling should only return a link to the principal url
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"code.vikunja.io/api/pkg/metrics"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
v1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"time"
|
||||
|
@ -51,7 +52,7 @@ func setupMetrics(a *echo.Group) {
|
|||
},
|
||||
{
|
||||
metrics.UserCountKey,
|
||||
models.User{},
|
||||
user.User{},
|
||||
},
|
||||
{
|
||||
metrics.NamespaceCountKey,
|
||||
|
|
|
@ -53,6 +53,7 @@ import (
|
|||
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
|
||||
"code.vikunja.io/api/pkg/routes/caldav"
|
||||
_ "code.vikunja.io/api/pkg/swagger" // To generate swagger docs
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
"code.vikunja.io/web"
|
||||
"code.vikunja.io/web/handler"
|
||||
"github.com/asaskevich/govalidator"
|
||||
|
@ -407,11 +408,11 @@ func registerCalDavRoutes(c *echo.Group) {
|
|||
}
|
||||
|
||||
func caldavBasicAuth(username, password string, c echo.Context) (bool, error) {
|
||||
creds := &models.UserLogin{
|
||||
creds := &user.Login{
|
||||
Username: username,
|
||||
Password: password,
|
||||
}
|
||||
u, err := models.CheckUserCredentials(creds)
|
||||
u, err := user.CheckUserCredentials(creds)
|
||||
if err != nil {
|
||||
log.Errorf("Error during basic auth for caldav: %v", err)
|
||||
return false, nil
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2018-2020 Vikunja and contriubtors. All rights reserved.
|
||||
//
|
||||
// This file is part of Vikunja.
|
||||
//
|
||||
// Vikunja is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vikunja is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
var x *xorm.Engine
|
||||
|
||||
// InitDB sets up the database connection to use in this module
|
||||
func InitDB() (err error) {
|
||||
x, err = db.CreateDBEngine()
|
||||
if err != nil {
|
||||
log.Criticalf("Could not connect to db: %v", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Cache
|
||||
if config.CacheEnabled.GetBool() && config.CacheType.GetString() == "redis" {
|
||||
db.RegisterTableStructsForCache(GetTables())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTables returns all structs which are also a table.
|
||||
func GetTables() []interface{} {
|
||||
return []interface{}{
|
||||
&User{},
|
||||
}
|
||||
}
|
|
@ -0,0 +1,291 @@
|
|||
// Copyright2018-2020 Vikunja and contriubtors. All rights reserved.
|
||||
//
|
||||
// This file is part of Vikunja.
|
||||
//
|
||||
// Vikunja is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Vikunja is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"code.vikunja.io/web"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// =====================
|
||||
// User Operation Errors
|
||||
// =====================
|
||||
|
||||
// ErrUsernameExists represents a "UsernameAlreadyExists" kind of error.
|
||||
type ErrUsernameExists struct {
|
||||
UserID int64
|
||||
Username string
|
||||
}
|
||||
|
||||
// IsErrUsernameExists checks if an error is a ErrUsernameExists.
|
||||
func IsErrUsernameExists(err error) bool {
|
||||
_, ok := err.(ErrUsernameExists)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUsernameExists) Error() string {
|
||||
return fmt.Sprintf("User with that username already exists [user id: %d, username: %s]", err.UserID, err.Username)
|
||||
}
|
||||
|
||||
// ErrorCodeUsernameExists holds the unique world-error code of this error
|
||||
const ErrorCodeUsernameExists = 1001
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrUsernameExists) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrorCodeUsernameExists, Message: "A user with this username already exists."}
|
||||
}
|
||||
|
||||
// ErrUserEmailExists represents a "UserEmailExists" kind of error.
|
||||
type ErrUserEmailExists struct {
|
||||
UserID int64
|
||||
Email string
|
||||
}
|
||||
|
||||
// IsErrUserEmailExists checks if an error is a ErrUserEmailExists.
|
||||
func IsErrUserEmailExists(err error) bool {
|
||||
_, ok := err.(ErrUserEmailExists)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUserEmailExists) Error() string {
|
||||
return fmt.Sprintf("User with that email already exists [user id: %d, email: %s]", err.UserID, err.Email)
|
||||
}
|
||||
|
||||
// ErrorCodeUserEmailExists holds the unique world-error code of this error
|
||||
const ErrorCodeUserEmailExists = 1002
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrUserEmailExists) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrorCodeUserEmailExists, Message: "A user with this email address already exists."}
|
||||
}
|
||||
|
||||
// ErrNoUsernamePassword represents a "NoUsernamePassword" kind of error.
|
||||
type ErrNoUsernamePassword struct{}
|
||||
|
||||
// IsErrNoUsernamePassword checks if an error is a ErrNoUsernamePassword.
|
||||
func IsErrNoUsernamePassword(err error) bool {
|
||||
_, ok := err.(ErrNoUsernamePassword)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrNoUsernamePassword) Error() string {
|
||||
return fmt.Sprintf("No username and password provided")
|
||||
}
|
||||
|
||||
// ErrCodeNoUsernamePassword holds the unique world-error code of this error
|
||||
const ErrCodeNoUsernamePassword = 1004
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrNoUsernamePassword) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeNoUsernamePassword, Message: "Please specify a username and a password."}
|
||||
}
|
||||
|
||||
// ErrUserDoesNotExist represents a "UserDoesNotExist" kind of error.
|
||||
type ErrUserDoesNotExist struct {
|
||||
UserID int64
|
||||
}
|
||||
|
||||
// IsErrUserDoesNotExist checks if an error is a ErrUserDoesNotExist.
|
||||
func IsErrUserDoesNotExist(err error) bool {
|
||||
_, ok := err.(ErrUserDoesNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUserDoesNotExist) Error() string {
|
||||
return fmt.Sprintf("User does not exist [user id: %d]", err.UserID)
|
||||
}
|
||||
|
||||
// ErrCodeUserDoesNotExist holds the unique world-error code of this error
|
||||
const ErrCodeUserDoesNotExist = 1005
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrUserDoesNotExist) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeUserDoesNotExist, Message: "The user does not exist."}
|
||||
}
|
||||
|
||||
// ErrCouldNotGetUserID represents a "ErrCouldNotGetUserID" kind of error.
|
||||
type ErrCouldNotGetUserID struct{}
|
||||
|
||||
// IsErrCouldNotGetUserID checks if an error is a ErrCouldNotGetUserID.
|
||||
func IsErrCouldNotGetUserID(err error) bool {
|
||||
_, ok := err.(ErrCouldNotGetUserID)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrCouldNotGetUserID) Error() string {
|
||||
return fmt.Sprintf("Could not get user ID")
|
||||
}
|
||||
|
||||
// ErrCodeCouldNotGetUserID holds the unique world-error code of this error
|
||||
const ErrCodeCouldNotGetUserID = 1006
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrCouldNotGetUserID) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeCouldNotGetUserID, Message: "Could not get user id."}
|
||||
}
|
||||
|
||||
// ErrNoPasswordResetToken represents an error where no password reset token exists for that user
|
||||
type ErrNoPasswordResetToken struct {
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (err ErrNoPasswordResetToken) Error() string {
|
||||
return fmt.Sprintf("No token to reset a password [UserID: %d]", err.UserID)
|
||||
}
|
||||
|
||||
// ErrCodeNoPasswordResetToken holds the unique world-error code of this error
|
||||
const ErrCodeNoPasswordResetToken = 1008
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrNoPasswordResetToken) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeNoPasswordResetToken, Message: "No token to reset a user's password provided."}
|
||||
}
|
||||
|
||||
// ErrInvalidPasswordResetToken is an error where the password reset token is invalid
|
||||
type ErrInvalidPasswordResetToken struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
func (err ErrInvalidPasswordResetToken) Error() string {
|
||||
return fmt.Sprintf("Invalid token to reset a password [Token: %s]", err.Token)
|
||||
}
|
||||
|
||||
// ErrCodeInvalidPasswordResetToken holds the unique world-error code of this error
|
||||
const ErrCodeInvalidPasswordResetToken = 1009
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrInvalidPasswordResetToken) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeInvalidPasswordResetToken, Message: "Invalid token to reset a user's password."}
|
||||
}
|
||||
|
||||
// IsErrInvalidPasswordResetToken checks if an error is a ErrInvalidPasswordResetToken.
|
||||
func IsErrInvalidPasswordResetToken(err error) bool {
|
||||
_, ok := err.(ErrInvalidPasswordResetToken)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrInvalidEmailConfirmToken is an error where the email confirm token is invalid
|
||||
type ErrInvalidEmailConfirmToken struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
func (err ErrInvalidEmailConfirmToken) Error() string {
|
||||
return fmt.Sprintf("Invalid email confirm token [Token: %s]", err.Token)
|
||||
}
|
||||
|
||||
// ErrCodeInvalidEmailConfirmToken holds the unique world-error code of this error
|
||||
const ErrCodeInvalidEmailConfirmToken = 1010
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrInvalidEmailConfirmToken) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeInvalidEmailConfirmToken, Message: "Invalid email confirm token."}
|
||||
}
|
||||
|
||||
// IsErrInvalidEmailConfirmToken checks if an error is a ErrInvalidEmailConfirmToken.
|
||||
func IsErrInvalidEmailConfirmToken(err error) bool {
|
||||
_, ok := err.(ErrInvalidEmailConfirmToken)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrWrongUsernameOrPassword is an error where the email was not confirmed
|
||||
type ErrWrongUsernameOrPassword struct {
|
||||
}
|
||||
|
||||
func (err ErrWrongUsernameOrPassword) Error() string {
|
||||
return fmt.Sprintf("Wrong username or password")
|
||||
}
|
||||
|
||||
// ErrCodeWrongUsernameOrPassword holds the unique world-error code of this error
|
||||
const ErrCodeWrongUsernameOrPassword = 1011
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrWrongUsernameOrPassword) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeWrongUsernameOrPassword, Message: "Wrong username or password."}
|
||||
}
|
||||
|
||||
// IsErrWrongUsernameOrPassword checks if an error is a IsErrEmailNotConfirmed.
|
||||
func IsErrWrongUsernameOrPassword(err error) bool {
|
||||
_, ok := err.(ErrWrongUsernameOrPassword)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrEmailNotConfirmed is an error where the email was not confirmed
|
||||
type ErrEmailNotConfirmed struct {
|
||||
UserID int64
|
||||
}
|
||||
|
||||
func (err ErrEmailNotConfirmed) Error() string {
|
||||
return fmt.Sprintf("Email is not confirmed [UserID: %d]", err.UserID)
|
||||
}
|
||||
|
||||
// ErrCodeEmailNotConfirmed holds the unique world-error code of this error
|
||||
const ErrCodeEmailNotConfirmed = 1012
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrEmailNotConfirmed) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeEmailNotConfirmed, Message: "Please confirm your email address."}
|
||||
}
|
||||
|
||||
// IsErrEmailNotConfirmed checks if an error is a IsErrEmailNotConfirmed.
|
||||
func IsErrEmailNotConfirmed(err error) bool {
|
||||
_, ok := err.(ErrEmailNotConfirmed)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ErrEmptyNewPassword represents a "EmptyNewPassword" kind of error.
|
||||
type ErrEmptyNewPassword struct{}
|
||||
|
||||
// IsErrEmptyNewPassword checks if an error is a ErrEmptyNewPassword.
|
||||
func IsErrEmptyNewPassword(err error) bool {
|
||||
_, ok := err.(ErrEmptyNewPassword)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrEmptyNewPassword) Error() string {
|
||||
return fmt.Sprintf("New password is empty")
|
||||
}
|
||||
|
||||
// ErrCodeEmptyNewPassword holds the unique world-error code of this error
|
||||
const ErrCodeEmptyNewPassword = 1013
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrEmptyNewPassword) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeEmptyNewPassword, Message: "Please specify new password."}
|
||||
}
|
||||
|
||||
// ErrEmptyOldPassword represents a "EmptyOldPassword" kind of error.
|
||||
type ErrEmptyOldPassword struct{}
|
||||
|
||||
// IsErrEmptyOldPassword checks if an error is a ErrEmptyOldPassword.
|
||||
func IsErrEmptyOldPassword(err error) bool {
|
||||
_, ok := err.(ErrEmptyOldPassword)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrEmptyOldPassword) Error() string {
|
||||
return fmt.Sprintf("Old password is empty")
|
||||
}
|
||||
|
||||
// ErrCodeEmptyOldPassword holds the unique world-error code of this error
|
||||
const ErrCodeEmptyOldPassword = 1014
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrEmptyOldPassword) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{HTTPCode: http.StatusPreconditionFailed, Code: ErrCodeEmptyOldPassword, Message: "Please specify old password."}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue