binwiederhier 7 mesiacov pred
rodič
commit
4457e9e26f
2 zmenil súbory, kde vykonal 173 pridanie a 27 odobranie
  1. 74 7
      user/manager.go
  2. 99 20
      user/manager_test.go

+ 74 - 7
user/manager.go

@@ -316,7 +316,7 @@ const (
 
 // Schema management queries
 const (
-	currentSchemaVersion     = 5
+	currentSchemaVersion     = 6
 	insertSchemaVersion      = `INSERT INTO schemaVersion VALUES (1, ?)`
 	updateSchemaVersion      = `UPDATE schemaVersion SET version = ? WHERE id = 1`
 	selectSchemaVersionQuery = `SELECT version FROM schemaVersion WHERE id = 1`
@@ -434,11 +434,78 @@ const (
 
 	// 5 -> 6
 	migrate5To6UpdateQueries = `
-		ALTER TABLE user ADD COLUMN provisioned INT NOT NULL DEFAULT (0);
-		ALTER TABLE user ALTER COLUMN provisioned DROP DEFAULT;
+		PRAGMA foreign_keys=off;
 
-		ALTER TABLE user_access ADD COLUMN provisioned INT NOT NULL DEFAULT (0);
-		ALTER TABLE user_access ALTER COLUMN provisioned DROP DEFAULT;
+		-- Alter user table: Add provisioned column
+		ALTER TABLE user RENAME TO user_old;
+		CREATE TABLE IF NOT EXISTS user (
+		    id TEXT PRIMARY KEY,
+			tier_id TEXT,
+			user TEXT NOT NULL,
+			pass TEXT NOT NULL,
+			role TEXT CHECK (role IN ('anonymous', 'admin', 'user')) NOT NULL,
+			prefs JSON NOT NULL DEFAULT '{}',
+			sync_topic TEXT NOT NULL,
+			provisioned INT NOT NULL,
+			stats_messages INT NOT NULL DEFAULT (0),
+			stats_emails INT NOT NULL DEFAULT (0),
+			stats_calls INT NOT NULL DEFAULT (0),
+			stripe_customer_id TEXT,
+			stripe_subscription_id TEXT,
+			stripe_subscription_status TEXT,
+			stripe_subscription_interval TEXT,
+			stripe_subscription_paid_until INT,
+			stripe_subscription_cancel_at INT,
+			created INT NOT NULL,
+			deleted INT,
+		    FOREIGN KEY (tier_id) REFERENCES tier (id)
+		);
+		INSERT INTO user
+		SELECT
+		    id,
+		    tier_id,
+		    user,
+		    pass,
+		    role,
+		    prefs,
+		    sync_topic,
+		    0,
+		    stats_messages,
+		    stats_emails,
+		    stats_calls,
+		    stripe_customer_id,
+		    stripe_subscription_id,
+		    stripe_subscription_status,
+		    stripe_subscription_interval,
+		    stripe_subscription_paid_until,
+		    stripe_subscription_cancel_at,
+		    created, deleted
+		FROM user_old;
+		DROP TABLE user_old;
+
+		-- Alter user_access table: Add provisioned column
+		ALTER TABLE user_access RENAME TO user_access_old;
+		CREATE TABLE user_access (
+			user_id TEXT NOT NULL,
+			topic TEXT NOT NULL,
+			read INT NOT NULL,
+			write INT NOT NULL,
+			owner_user_id INT,
+			provisioned INTEGER NOT NULL,
+			PRIMARY KEY (user_id, topic),
+			FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE,
+			FOREIGN KEY (owner_user_id) REFERENCES user (id) ON DELETE CASCADE
+		);
+		INSERT INTO user_access SELECT *, 0 FROM user_access_old;
+		DROP TABLE user_access_old;
+
+		-- Recreate indices
+		CREATE UNIQUE INDEX idx_user ON user (user);
+		CREATE UNIQUE INDEX idx_user_stripe_customer_id ON user (stripe_customer_id);
+		CREATE UNIQUE INDEX idx_user_stripe_subscription_id ON user (stripe_subscription_id);
+
+		-- Re-enable foreign keys
+		PRAGMA foreign_keys=on;
 	`
 )
 
@@ -1422,10 +1489,10 @@ func (a *Manager) AddReservation(username string, topic string, everyone Permiss
 		return err
 	}
 	defer tx.Rollback()
-	if _, err := tx.Exec(upsertUserAccessQuery, username, escapeUnderscore(topic), true, true, username, username); err != nil {
+	if _, err := tx.Exec(upsertUserAccessQuery, username, escapeUnderscore(topic), true, true, username, username, false); err != nil {
 		return err
 	}
-	if _, err := tx.Exec(upsertUserAccessQuery, Everyone, escapeUnderscore(topic), everyone.IsRead(), everyone.IsWrite(), username, username); err != nil {
+	if _, err := tx.Exec(upsertUserAccessQuery, Everyone, escapeUnderscore(topic), everyone.IsRead(), everyone.IsWrite(), username, username, false); err != nil {
 		return err
 	}
 	return tx.Commit()

+ 99 - 20
user/manager_test.go

@@ -52,10 +52,10 @@ func TestManager_FullScenario_Default_DenyAll(t *testing.T) {
 	benGrants, err := a.Grants("ben")
 	require.Nil(t, err)
 	require.Equal(t, []Grant{
-		{"everyonewrite", PermissionDenyAll},
-		{"mytopic", PermissionReadWrite},
-		{"writeme", PermissionWrite},
-		{"readme", PermissionRead},
+		{"everyonewrite", PermissionDenyAll, false},
+		{"mytopic", PermissionReadWrite, false},
+		{"writeme", PermissionWrite, false},
+		{"readme", PermissionRead, false},
 	}, benGrants)
 
 	john, err := a.Authenticate("john", "john")
@@ -67,10 +67,10 @@ func TestManager_FullScenario_Default_DenyAll(t *testing.T) {
 	johnGrants, err := a.Grants("john")
 	require.Nil(t, err)
 	require.Equal(t, []Grant{
-		{"mytopic_deny*", PermissionDenyAll},
-		{"mytopic_ro*", PermissionRead},
-		{"mytopic*", PermissionReadWrite},
-		{"*", PermissionRead},
+		{"mytopic_deny*", PermissionDenyAll, false},
+		{"mytopic_ro*", PermissionRead, false},
+		{"mytopic*", PermissionReadWrite, false},
+		{"*", PermissionRead, false},
 	}, johnGrants)
 
 	notben, err := a.Authenticate("ben", "this is wrong")
@@ -277,10 +277,10 @@ func TestManager_UserManagement(t *testing.T) {
 	benGrants, err := a.Grants("ben")
 	require.Nil(t, err)
 	require.Equal(t, []Grant{
-		{"everyonewrite", PermissionDenyAll},
-		{"mytopic", PermissionReadWrite},
-		{"writeme", PermissionWrite},
-		{"readme", PermissionRead},
+		{"everyonewrite", PermissionDenyAll, false},
+		{"mytopic", PermissionReadWrite, false},
+		{"writeme", PermissionWrite, false},
+		{"readme", PermissionRead, false},
 	}, benGrants)
 
 	everyone, err := a.User(Everyone)
@@ -292,8 +292,8 @@ func TestManager_UserManagement(t *testing.T) {
 	everyoneGrants, err := a.Grants(Everyone)
 	require.Nil(t, err)
 	require.Equal(t, []Grant{
-		{"everyonewrite", PermissionReadWrite},
-		{"announcements", PermissionRead},
+		{"everyonewrite", PermissionReadWrite, false},
+		{"announcements", PermissionRead, false},
 	}, everyoneGrants)
 
 	// Ben: Before revoking
@@ -1099,19 +1099,98 @@ func TestManager_Topic_Wildcard_With_Underscore(t *testing.T) {
 func TestManager_WithProvisionedUsers(t *testing.T) {
 	f := filepath.Join(t.TempDir(), "user.db")
 	conf := &Config{
-		Filename:      f,
-		DefaultAccess: PermissionReadWrite,
-		ProvisionedUsers: []*User{
-			{Name: "phil", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleAdmin},
+		Filename:         f,
+		DefaultAccess:    PermissionReadWrite,
+		ProvisionEnabled: true,
+		ProvisionUsers: []*User{
+			{Name: "philuser", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleUser},
+			{Name: "philadmin", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleAdmin},
+		},
+		ProvisionAccess: map[string][]*Grant{
+			"philuser": {
+				{TopicPattern: "stats", Permission: PermissionReadWrite},
+				{TopicPattern: "secret", Permission: PermissionRead},
+			},
 		},
 	}
 	a, err := NewManager(conf)
 	require.Nil(t, err)
+
+	// Manually add user
+	require.Nil(t, a.AddUser("philmanual", "manual", RoleUser, false))
+
+	// Check that the provisioned users are there
 	users, err := a.Users()
 	require.Nil(t, err)
-	for _, u := range users {
-		fmt.Println(u.ID, u.Name, u.Role)
+	require.Len(t, users, 4)
+
+	require.Equal(t, "philadmin", users[0].Name)
+	require.Equal(t, RoleAdmin, users[0].Role)
+
+	require.Equal(t, "philmanual", users[1].Name)
+	require.Equal(t, RoleUser, users[1].Role)
+
+	grants, err := a.Grants("philuser")
+	require.Nil(t, err)
+	require.Equal(t, "philuser", users[2].Name)
+	require.Equal(t, RoleUser, users[2].Role)
+	require.Equal(t, 2, len(grants))
+	require.Equal(t, "secret", grants[0].TopicPattern)
+	require.Equal(t, PermissionRead, grants[0].Permission)
+	require.Equal(t, "stats", grants[1].TopicPattern)
+	require.Equal(t, PermissionReadWrite, grants[1].Permission)
+
+	require.Equal(t, "*", users[3].Name)
+
+	// Re-open the DB (second app start)
+	require.Nil(t, a.db.Close())
+	conf.ProvisionUsers = []*User{
+		{Name: "philuser", Hash: "$2a$10$AAAU21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleUser},
 	}
+	conf.ProvisionAccess = map[string][]*Grant{
+		"philuser": {
+			{TopicPattern: "stats12", Permission: PermissionReadWrite},
+			{TopicPattern: "secret12", Permission: PermissionRead},
+		},
+	}
+	a, err = NewManager(conf)
+	require.Nil(t, err)
+
+	// Check that the provisioned users are there
+	users, err = a.Users()
+	require.Nil(t, err)
+	require.Len(t, users, 3)
+
+	require.Equal(t, "philmanual", users[0].Name)
+	require.Equal(t, RoleUser, users[0].Role)
+
+	grants, err = a.Grants("philuser")
+	require.Nil(t, err)
+	require.Equal(t, "philuser", users[1].Name)
+	require.Equal(t, RoleUser, users[1].Role)
+	require.Equal(t, 2, len(grants))
+	require.Equal(t, "secret12", grants[0].TopicPattern)
+	require.Equal(t, PermissionRead, grants[0].Permission)
+	require.Equal(t, "stats12", grants[1].TopicPattern)
+	require.Equal(t, PermissionReadWrite, grants[1].Permission)
+
+	require.Equal(t, "*", users[2].Name)
+
+	// Re-open the DB again (third app start)
+	require.Nil(t, a.db.Close())
+	conf.ProvisionUsers = []*User{}
+	conf.ProvisionAccess = map[string][]*Grant{}
+	a, err = NewManager(conf)
+	require.Nil(t, err)
+
+	// Check that the provisioned users are there
+	users, err = a.Users()
+	require.Nil(t, err)
+	require.Len(t, users, 2)
+
+	require.Equal(t, "philmanual", users[0].Name)
+	require.Equal(t, RoleUser, users[0].Role)
+	require.Equal(t, "*", users[1].Name)
 }
 
 func TestToFromSQLWildcard(t *testing.T) {