aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--sqlite3.go10
-rw-r--r--sqlite3.goconvey11
-rw-r--r--sqlite3_opt_userauth_test.go1193
-rw-r--r--upgrade/package.go7
-rw-r--r--upgrade/profile.goconvey2
6 files changed, 1066 insertions, 158 deletions
diff --git a/.travis.yml b/.travis.yml
index ba8c891..2dca239 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -88,6 +88,7 @@ before_install:
fi
- |
if [[ "${GOOS}" != "windows" ]]; then
+ go get github.com/smartystreets/goconvey
go get github.com/mattn/goveralls
go get golang.org/x/tools/cmd/cover
fi
diff --git a/sqlite3.go b/sqlite3.go
index 4b33726..e6f8c55 100644
--- a/sqlite3.go
+++ b/sqlite3.go
@@ -1306,7 +1306,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
//
// If the SQLITE_USER table is not present in the database file, then
// this interface is a harmless no-op returnning SQLITE_OK.
- if err := conn.RegisterFunc("authenticate", conn.authenticate, false); err != nil {
+ if err := conn.RegisterFunc("authenticate", conn.authenticate, true); err != nil {
return nil, err
}
//
@@ -1319,7 +1319,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// The AuthUserAdd only works for the "main" database, not
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
// non-admin user results in an error.
- if err := conn.RegisterFunc("auth_user_add", conn.authUserAdd, false); err != nil {
+ if err := conn.RegisterFunc("auth_user_add", conn.authUserAdd, true); err != nil {
return nil, err
}
//
@@ -1329,7 +1329,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// login credentials. Only an admin user can change another users login
// credentials or admin privilege setting. No user may change their own
// admin privilege setting.
- if err := conn.RegisterFunc("auth_user_change", conn.authUserChange, false); err != nil {
+ if err := conn.RegisterFunc("auth_user_change", conn.authUserChange, true); err != nil {
return nil, err
}
//
@@ -1339,13 +1339,13 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// which guarantees that there is always an admin user and hence that
// the database cannot be converted into a no-authentication-required
// database.
- if err := conn.RegisterFunc("auth_user_delete", conn.authUserDelete, false); err != nil {
+ if err := conn.RegisterFunc("auth_user_delete", conn.authUserDelete, true); err != nil {
return nil, err
}
// Register: auth_enabled
// auth_enabled can be used to check if user authentication is enabled
- if err := conn.RegisterFunc("auth_enabled", conn.authEnabled, false); err != nil {
+ if err := conn.RegisterFunc("auth_enabled", conn.authEnabled, true); err != nil {
return nil, err
}
diff --git a/sqlite3.goconvey b/sqlite3.goconvey
new file mode 100644
index 0000000..73c2bb6
--- /dev/null
+++ b/sqlite3.goconvey
@@ -0,0 +1,11 @@
+// GoConvey Test Profile
+
+// Activate Coverage
+-cover
+
+-run=TestUserAuthentication
+
+// Test Flags
+-tags=sqlite_userauth
+
+// EOF \ No newline at end of file
diff --git a/sqlite3_opt_userauth_test.go b/sqlite3_opt_userauth_test.go
index 4755550..fbe1b92 100644
--- a/sqlite3_opt_userauth_test.go
+++ b/sqlite3_opt_userauth_test.go
@@ -9,201 +9,1088 @@ package sqlite3
import (
"database/sql"
+ "fmt"
"os"
"testing"
+
+ . "github.com/smartystreets/goconvey/convey"
)
-func TestAuthCreateDatabase(t *testing.T) {
- tempFilename := TempFilename(t)
- defer os.Remove(tempFilename)
+func init() {
- db, err := sql.Open("sqlite3", "file:"+tempFilename+"?_auth&_auth_user=admin&_auth_pass=admin")
- if err != nil {
- t.Fatal("Failed to open database:", err)
- }
- defer db.Close()
+}
- var exists bool
- err = db.QueryRow("select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';").Scan(&exists)
- if err != nil {
- t.Fatal(err)
- }
+func TestUserAuthentication(t *testing.T) {
+ // Create database connection
+ var conn *SQLiteConn
+ sql.Register("sqlite3_with_conn",
+ &SQLiteDriver{
+ ConnectHook: func(c *SQLiteConn) error {
+ conn = c
+ return nil
+ },
+ })
- if !exists {
- t.Fatal("failed to enable User Authentication")
- }
-}
+ connect := func(f string, username, password string) (file string, db *sql.DB, c *SQLiteConn, err error) {
+ conn = nil // Clear connection
+ file = f // Copy provided file (f) => file
+ if file == "" {
+ // Create dummy file
+ file = TempFilename(t)
+ }
-func TestAuthorization(t *testing.T) {
- tempFilename := TempFilename(t)
- defer os.Remove(tempFilename)
+ db, err = sql.Open("sqlite3_with_conn", "file:"+file+fmt.Sprintf("?_auth&_auth_user=%s&_auth_pass=%s", username, password))
+ if err != nil {
+ defer os.Remove(file)
+ return file, nil, nil, err
+ }
- db, err := sql.Open("sqlite3", "file:"+tempFilename+"?_auth&_auth_user=admin&_auth_pass=admin")
- if err != nil {
- t.Fatal("Failed to open database:", err)
- }
+ // Dummy query to force connection and database creation
+ // Will return ErrUnauthorized (SQLITE_AUTH) if user authentication fails
+ if _, err = db.Exec("SELECT 1;"); err != nil {
+ defer os.Remove(file)
+ defer db.Close()
+ return file, nil, nil, err
+ }
+ c = conn
- // Dummy Query to force connection
- if _, err := db.Exec("SELECT 1;"); err != nil {
- t.Fatalf("Failed to connect: %s", err)
+ return
}
- // Add normal user to database
- if _, err := db.Exec("select auth_user_add('user', 'user', false);"); err != nil {
- t.Fatal(err)
+ authEnabled := func(db *sql.DB) (exists bool, err error) {
+ err = db.QueryRow("select count(type) from sqlite_master WHERE type='table' and name='sqlite_user';").Scan(&exists)
+ return
}
- var uname string
- if err := db.QueryRow("select uname from sqlite_user where uname = 'user';").Scan(&uname); err != nil {
- t.Fatal(err)
+ addUser := func(db *sql.DB, username, password string, admin int) (rv int, err error) {
+ err = db.QueryRow("select auth_user_add(?, ?, ?);", username, password, admin).Scan(&rv)
+ return
}
- if uname != "user" {
- t.Fatal("Failed to create normal user")
+
+ userExists := func(db *sql.DB, username string) (rv int, err error) {
+ err = db.QueryRow("select count(uname) from sqlite_user where uname=?", username).Scan(&rv)
+ return
}
- db.Close()
- // Re-Open Database as User
- db, err = sql.Open("sqlite3", "file:"+tempFilename+"?_auth_user=user&_auth_pass=user")
- if err != nil {
- t.Fatal("Failed to open database:", err)
+ isAdmin := func(db *sql.DB, username string) (rv bool, err error) {
+ err = db.QueryRow("select isAdmin from sqlite_user where uname=?", username).Scan(&rv)
+ return
}
- defer db.Close()
- // Add User should now fail because we are not admin
- var rv int
- if err := db.QueryRow("select auth_user_add('user2', 'user2', false);").Scan(&rv); err != nil || rv == 0 {
- if err != nil {
- t.Fatal(err)
- }
- t.Fatal("Succeeded creating user, while not being admin, this is not supposed to work")
+ modifyUser := func(db *sql.DB, username, password string, admin int) (rv int, err error) {
+ err = db.QueryRow("select auth_user_change(?, ?, ?);", username, password, admin).Scan(&rv)
+ return
}
- // Try to create admin user
- // Should also fail because we are not admin
- if err := db.QueryRow("select auth_user_add('admin2', 'admin2', true);").Scan(&rv); err != nil || rv == 0 {
- if err != nil {
- t.Fatal(err)
- }
- t.Fatal("Succeeded creating admin, while not being admin, this is not supposed to work")
+ deleteUser := func(db *sql.DB, username string) (rv int, err error) {
+ err = db.QueryRow("select auth_user_delete(?);", username).Scan(&rv)
+ return
}
-}
-func TestAuthorizationFailed(t *testing.T) {
- tempFilename := TempFilename(t)
- defer os.Remove(tempFilename)
+ Convey("Create Database", t, func() {
+ _, db, c, err := connect("", "admin", "admin")
+ So(db, ShouldNotBeNil)
+ So(c, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db.Close()
- db, err := sql.Open("sqlite3", "file:"+tempFilename+"?_auth&_auth_user=admin&_auth_pass=admin")
- if err != nil {
- t.Fatal("Failed to open database:", err)
- }
+ b, err := authEnabled(db)
+ So(b, ShouldEqual, true)
+ So(err, ShouldBeNil)
- // Dummy Query to force connection
- if _, err := db.Exec("SELECT 1;"); err != nil {
- t.Fatalf("Failed to connect: %s", err)
- }
- db.Close()
+ e, err := userExists(db, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
- db, err = sql.Open("sqlite3", "file:"+tempFilename+"?_auth&_auth_user=admin&_auth_pass=invalid")
- if err != nil {
- t.Fatal("Failed to open database:", err)
- }
- defer db.Close()
+ a, err := isAdmin(db, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+ })
- // Dummy Query to issue connection
- if _, err := db.Exec("SELECT 1;"); err != nil && err != ErrUnauthorized {
- t.Fatalf("Failed to connect: %s", err)
- }
-}
+ Convey("Authorization Success", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
-func TestAuthUserModify(t *testing.T) {
- tempFilename := TempFilename(t)
- defer os.Remove(tempFilename)
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
- var rv int
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+ db1.Close()
- db, err := sql.Open("sqlite3", "file:"+tempFilename+"?_auth&_auth_user=admin&_auth_pass=admin")
- if err != nil {
- t.Fatal("Failed to open database:", err)
- }
+ // Preform authentication
+ f2, db2, c2, err := connect(f1, "admin", "admin")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+ })
- // Dummy Query to force connection
- if _, err := db.Exec("SELECT 1;"); err != nil {
- t.Fatalf("Failed to connect: %s", err)
- }
+ Convey("Authorization Success (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db1.Close()
- if err := db.QueryRow("select auth_user_add('user', 'user', false);").Scan(&rv); err != nil || rv != 0 {
- if err != nil {
- t.Fatal(err)
- }
- t.Fatal("Failed to create normal user")
- }
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
- if err := db.QueryRow("select auth_user_change('admin', 'nimda', true);").Scan(&rv); err != nil || rv != 0 {
- if err != nil {
- t.Fatal(err)
- }
- t.Fatal("Failed to change password")
- }
- db.Close()
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
- // Re-Connect with new credentials
- db, err = sql.Open("sqlite3", "file:"+tempFilename+"?_auth_user=admin&_auth_pass=nimda")
- if err != nil {
- t.Fatal("Failed to open database:", err)
- }
+ // Test lower level authentication
+ err = c1.Authenticate("admin", "admin")
+ So(err, ShouldBeNil)
+ })
- if err := db.QueryRow("select count(uname) from sqlite_user where uname = 'admin';").Scan(&rv); err != nil {
- t.Fatal(err)
- }
- defer db.Close()
+ Convey("Authorization Failed", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
- // Dummy Query to force connection to test authorization
- if _, err := db.Exec("SELECT 1;"); err != nil && err != ErrUnauthorized {
- t.Fatalf("Failed to connect: %s", err)
- }
-}
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
-func TestAuthUserDelete(t *testing.T) {
- tempFilename := TempFilename(t)
- defer os.Remove(tempFilename)
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
- var rv int
+ // Perform Invalid Authentication when we connect
+ // to a database
+ f2, db2, c2, err := connect(f1, "admin", "invalid")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldBeNil)
+ So(c2, ShouldBeNil)
+ So(err, ShouldEqual, ErrUnauthorized)
+ })
- db, err := sql.Open("sqlite3", "file:"+tempFilename+"?_auth&_auth_user=admin&_auth_pass=admin")
- if err != nil {
- t.Fatal("Failed to open database:", err)
- }
- defer db.Close()
+ Convey("Authorization Failed (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db1.Close()
- // Dummy Query to force connection to test authorization
- if _, err := db.Exec("SELECT 1;"); err != nil {
- t.Fatalf("Failed to connect: %s", err)
- }
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
- // Add User
- if _, err := db.Exec("select auth_user_add('user', 'user', false);"); err != nil {
- t.Fatal(err)
- }
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
- // Verify, their should be now 2 users
- var users int
- if err := db.QueryRow("select count(uname) from sqlite_user;").Scan(&users); err != nil {
- t.Fatal(err)
- }
- if users != 2 {
- t.Fatal("Failed to add user")
- }
+ // Test lower level authentication
+ // We require a successful *SQLiteConn to test this.
+ err = c1.Authenticate("admin", "invalid")
+ So(err, ShouldNotBeNil)
+ So(err, ShouldEqual, ErrUnauthorized)
+ })
- // Delete User
- if _, err := db.Exec("select auth_user_delete('user');"); err != nil {
- t.Fatal(err)
- }
+ Convey("Add Admin User", t, func() {
+ _, db, c, err := connect("", "admin", "admin")
+ So(db, ShouldNotBeNil)
+ So(c, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db.Close()
- // Verify their should now only be 1 user remaining, the current logged in admin user
- if err := db.QueryRow("select count(uname) from sqlite_user;").Scan(&users); err != nil {
- t.Fatal(err)
- }
- if users != 1 {
- t.Fatal("Failed to delete user")
- }
+ e, err := userExists(db, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Admin User
+ rv, err := addUser(db, "admin2", "admin2", 1)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db, "admin2")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db, "admin2")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+ })
+
+ Convey("Add Admin User (*SQLiteConn)", t, func() {
+ _, db, c, err := connect("", "admin", "admin")
+ So(db, ShouldNotBeNil)
+ So(c, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db.Close()
+
+ e, err := userExists(db, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Test lower level AuthUserAdd
+ err = c.AuthUserAdd("admin2", "admin2", true)
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db, "admin2")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db, "admin2")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+ })
+
+ Convey("Add Normal User", t, func() {
+ _, db, c, err := connect("", "admin", "admin")
+ So(db, ShouldNotBeNil)
+ So(c, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db.Close()
+
+ e, err := userExists(db, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ })
+
+ Convey("Add Normal User (*SQLiteConn)", t, func() {
+ _, db, c, err := connect("", "admin", "admin")
+ So(db, ShouldNotBeNil)
+ So(c, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db.Close()
+
+ e, err := userExists(db, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Test lower level AuthUserAdd
+ err = c.AuthUserAdd("user", "user", false)
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ })
+
+ Convey("Add Admin User Insufficient Privileges", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ db1.Close()
+
+ // Reconnect as normal user
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+
+ // Add Admin User
+ // Because 'user' is not admin
+ // Adding an admin user should now fail
+ // because we have insufficient privileges
+ rv, err = addUser(db2, "admin2", "admin2", 1)
+ So(rv, ShouldEqual, SQLITE_AUTH)
+ So(err, ShouldBeNil)
+ })
+
+ Convey("Add Admin User Insufficient Privileges (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ db1.Close()
+
+ // Reconnect as normal user
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+
+ // Add Admin User
+ // Because 'user' is not admin
+ // Adding an admin user should now fail
+ // because we have insufficient privileges
+ err = c2.AuthUserAdd("admin2", "admin2", true)
+ So(err, ShouldNotBeNil)
+ So(err, ShouldEqual, ErrAdminRequired)
+ })
+
+ Convey("Add Normal User Insufficient Privileges", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ db1.Close()
+
+ // Reconnect as normal user
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+
+ // Add Normal User
+ // Because 'user' is not admin
+ // Adding an normal user should now fail
+ // because we have insufficient privileges
+ rv, err = addUser(db2, "user2", "user2", 0)
+ So(rv, ShouldEqual, SQLITE_AUTH)
+ So(err, ShouldBeNil)
+ })
+
+ Convey("Add Normal User Insufficient Privileges (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ db1.Close()
+
+ // Reconnect as normal user
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+
+ // Add Normal User
+ // Because 'user' is not admin
+ // Adding an normal user should now fail
+ // because we have insufficient privileges
+ // Test lower level AuthUserAdd
+ err = c2.AuthUserAdd("user2", "user2", false)
+ So(err, ShouldNotBeNil)
+ So(err, ShouldEqual, ErrAdminRequired)
+ })
+
+ Convey("Modify Current Connection Password", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Modify Password
+ rv, err := modifyUser(db1, "admin", "admin2", 1)
+ So(err, ShouldBeNil)
+ So(rv, ShouldEqual, 0)
+ db1.Close()
+
+ // Reconnect with new password
+ f2, db2, c2, err := connect(f1, "admin", "admin2")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+ })
+
+ Convey("Modify Current Connection Password (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db1.Close()
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Modify password through (*SQLiteConn)
+ err = c1.AuthUserChange("admin", "admin2", true)
+ So(err, ShouldBeNil)
+
+ // Reconnect with new password
+ f2, db2, c2, err := connect(f1, "admin", "admin2")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+ })
+
+ Convey("Modify Current Connection Admin Flag", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db1.Close()
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Modify Administrator Flag
+ // Because we are current logged in as 'admin'
+ // Changing our own admin flag should fail.
+ rv, err := modifyUser(db1, "admin", "admin", 0)
+ So(err, ShouldBeNil)
+ So(rv, ShouldEqual, SQLITE_AUTH)
+ })
+
+ Convey("Modify Current Connection Admin Flag (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db1.Close()
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Modify admin flag through (*SQLiteConn)
+ // Because we are current logged in as 'admin'
+ // Changing our own admin flag should fail.
+ err = c1.AuthUserChange("admin", "admin", false)
+ So(err, ShouldNotBeNil)
+ So(err, ShouldEqual, ErrAdminRequired)
+ })
+
+ Convey("Modify Other User Password", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify User
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ // Modify Password for user
+ rv, err = modifyUser(db1, "user", "user2", 0)
+ So(err, ShouldBeNil)
+ So(rv, ShouldEqual, 0)
+ db1.Close()
+
+ // Reconnect as normal user with new password
+ f2, db2, c2, err := connect(f1, "user", "user2")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+ })
+
+ Convey("Modify Other User Password (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify User
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ // Modify user password through (*SQLiteConn)
+ // Because we are still logged in as admin
+ // this should succeed.
+ err = c1.AuthUserChange("admin", "admin", false)
+ So(err, ShouldNotBeNil)
+ })
+
+ Convey("Modify Other User Admin Flag", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify User
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ // Modify Password for user
+ // Because we are logged in as admin
+ // This call should succeed.
+ rv, err = modifyUser(db1, "user", "user", 1)
+ So(err, ShouldBeNil)
+ So(rv, ShouldEqual, 0)
+ db1.Close()
+
+ // Reconnect as normal user with new password
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+ })
+
+ Convey("Modify Other User Admin Flag (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify User
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ // Modify user password through (*SQLiteConn)
+ // Because we are still logged in as admin
+ // this should succeed.
+ err = c1.AuthUserChange("user", "user", true)
+ So(err, ShouldBeNil)
+ })
+
+ Convey("Modify Other User Password as Non-Admin", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Add Normal User
+ rv, err = addUser(db1, "user2", "user2", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify 'user'
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ // Verify 'user2'
+ e, err = userExists(db1, "user2")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user2")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ db1.Close()
+
+ // Reconnect as normal user
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+
+ // Modify password for user as normal user
+ // Because 'user' is not admin
+ // Modifying password as a normal user should now fail
+ // because we have insufficient privileges
+ rv, err = modifyUser(db2, "user2", "invalid", 0)
+ So(err, ShouldBeNil)
+ So(rv, ShouldEqual, SQLITE_AUTH)
+ })
+
+ Convey("Modify Other User Password as Non-Admin", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Add Normal User
+ rv, err = addUser(db1, "user2", "user2", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify 'user'
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ // Verify 'user2'
+ e, err = userExists(db1, "user2")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user2")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ db1.Close()
+
+ // Reconnect as normal user
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+
+ // Modify user password through (*SQLiteConn)
+ // for 'user2'
+ // Because 'user' is not admin
+ // Modifying password as a normal user should now fail
+ // because we have insufficient privileges
+ err = c2.AuthUserChange("user2", "invalid", false)
+ So(err, ShouldNotBeNil)
+ So(err, ShouldEqual, ErrAdminRequired)
+ })
+
+ Convey("Delete User as Admin", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify 'user'
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ rv, err = deleteUser(db1, "user")
+ So(err, ShouldBeNil)
+ So(rv, ShouldEqual, 0)
+
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 0)
+ })
+
+ Convey("Delete User as Admin (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify 'user'
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ err = c1.AuthUserDelete("user")
+ So(err, ShouldBeNil)
+
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 0)
+ })
+
+ Convey("Delete User as Non-Admin", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Add Normal User
+ rv, err = addUser(db1, "user2", "user2", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify 'user'
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ // Verify 'user2'
+ e, err = userExists(db1, "user2")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user2")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ db1.Close()
+
+ // Reconnect as normal user
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+
+ rv, err = deleteUser(db2, "user2")
+ So(err, ShouldBeNil)
+ So(rv, ShouldEqual, SQLITE_AUTH)
+ })
+
+ Convey("Delete User as Non-Admin (*SQLiteConn)", t, func() {
+ f1, db1, c1, err := connect("", "admin", "admin")
+ So(f1, ShouldNotBeBlank)
+ So(db1, ShouldNotBeNil)
+ So(c1, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+
+ e, err := userExists(db1, "admin")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err := isAdmin(db1, "admin")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, true)
+
+ // Add Normal User
+ rv, err := addUser(db1, "user", "user", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Add Normal User
+ rv, err = addUser(db1, "user2", "user2", 0)
+ So(rv, ShouldEqual, 0) // 0 == C.SQLITE_OK
+ So(err, ShouldBeNil)
+
+ // Verify 'user'
+ e, err = userExists(db1, "user")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+
+ // Verify 'user2'
+ e, err = userExists(db1, "user2")
+ So(err, ShouldBeNil)
+ So(e, ShouldEqual, 1)
+
+ a, err = isAdmin(db1, "user2")
+ So(err, ShouldBeNil)
+ So(a, ShouldEqual, false)
+ db1.Close()
+
+ // Reconnect as normal user
+ f2, db2, c2, err := connect(f1, "user", "user")
+ So(f2, ShouldNotBeBlank)
+ So(f1, ShouldEqual, f2)
+ So(db2, ShouldNotBeNil)
+ So(c2, ShouldNotBeNil)
+ So(err, ShouldBeNil)
+ defer db2.Close()
+
+ err = c2.AuthUserDelete("user2")
+ So(err, ShouldNotBeNil)
+ So(err, ShouldEqual, ErrAdminRequired)
+ })
}
diff --git a/upgrade/package.go b/upgrade/package.go
new file mode 100644
index 0000000..2b12a77
--- /dev/null
+++ b/upgrade/package.go
@@ -0,0 +1,7 @@
+// Package upgrade
+//
+// Dummy to ensure package can be loaded
+//
+// This file is to avoid the following error:
+// can't load package: package go-sqlite3/upgrade: build constraints exclude all Go files in go-sqlite3\upgrade
+package upgrade
diff --git a/upgrade/profile.goconvey b/upgrade/profile.goconvey
new file mode 100644
index 0000000..55049ab
--- /dev/null
+++ b/upgrade/profile.goconvey
@@ -0,0 +1,2 @@
+// Goconvey Profile
+IGNORE