mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-28 10:51:44 +01:00 
			
		
		
		
	fix constraints
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
		
							parent
							
								
									3780c9fd69
								
							
						
					
					
						commit
						7d9b430ec2
					
				| @ -498,6 +498,25 @@ func NewHeadscaleDatabase( | |||||||
| 						return err | 						return err | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
|  | 					// Set up indexes and unique constraints outside of GORM, it does not support
 | ||||||
|  | 					// conditional unique constraints.
 | ||||||
|  | 					// This ensures the following:
 | ||||||
|  | 					// - A user name and provider_identifier is unique
 | ||||||
|  | 					// - A provider_identifier is unique
 | ||||||
|  | 					// - A user name is unique if there is no provider_identifier is not set
 | ||||||
|  | 					for _, idx := range []string{ | ||||||
|  | 						"DROP INDEX IF EXISTS `idx_provider_identifier`", | ||||||
|  | 						"DROP INDEX IF EXISTS `idx_name_provider_identifier`", | ||||||
|  | 						"CREATE UNIQUE INDEX IF NOT EXISTS `idx_provider_identifier` ON `users` (`provider_identifier`) WHERE provider_identifier IS NOT NULL;", | ||||||
|  | 						"CREATE UNIQUE INDEX IF NOT EXISTS `idx_name_provider_identifier` ON `users` (`name`,`provider_identifier`);", | ||||||
|  | 						"CREATE UNIQUE INDEX IF NOT EXISTS `idx_name_no_provider_identifier` ON `users` (`name`) WHERE provider_identifier IS NULL;", | ||||||
|  | 					} { | ||||||
|  | 						err = tx.Exec(idx).Error | ||||||
|  | 						if err != nil { | ||||||
|  | 							return fmt.Errorf("creating username index: %w", err) | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 
 | ||||||
| 					return nil | 					return nil | ||||||
| 				}, | 				}, | ||||||
| 				Rollback: func(db *gorm.DB) error { return nil }, | 				Rollback: func(db *gorm.DB) error { return nil }, | ||||||
|  | |||||||
| @ -271,8 +271,8 @@ func TestConstraints(t *testing.T) { | |||||||
| 				require.NoError(t, err) | 				require.NoError(t, err) | ||||||
| 				_, err = CreateUser(db, "user1") | 				_, err = CreateUser(db, "user1") | ||||||
| 				require.Error(t, err) | 				require.Error(t, err) | ||||||
| 				// assert.Contains(t, err.Error(), "UNIQUE constraint failed: users.username")
 | 				assert.Contains(t, err.Error(), "UNIQUE constraint failed:") | ||||||
| 				require.Contains(t, err.Error(), "user already exists") | 				// require.Contains(t, err.Error(), "user already exists")
 | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| @ -295,7 +295,7 @@ func TestConstraints(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 				err = db.Save(&user).Error | 				err = db.Save(&user).Error | ||||||
| 				require.Error(t, err) | 				require.Error(t, err) | ||||||
| 				require.Contains(t, err.Error(), "UNIQUE constraint failed: users.provider_identifier") | 				require.Contains(t, err.Error(), "UNIQUE constraint failed:") | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| @ -318,7 +318,7 @@ func TestConstraints(t *testing.T) { | |||||||
| 
 | 
 | ||||||
| 				err = db.Save(&user).Error | 				err = db.Save(&user).Error | ||||||
| 				require.Error(t, err) | 				require.Error(t, err) | ||||||
| 				require.Contains(t, err.Error(), "UNIQUE constraint failed: users.provider_identifier") | 				require.Contains(t, err.Error(), "UNIQUE constraint failed:") | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| @ -328,9 +328,9 @@ func TestConstraints(t *testing.T) { | |||||||
| 				require.NoError(t, err) | 				require.NoError(t, err) | ||||||
| 
 | 
 | ||||||
| 				user := types.User{ | 				user := types.User{ | ||||||
| 					Name: "user1", | 					Name:               "user1", | ||||||
|  | 					ProviderIdentifier: sql.NullString{String: "http://test.com/user1", Valid: true}, | ||||||
| 				} | 				} | ||||||
| 				user.ProviderIdentifier.String = "http://test.com/user1" |  | ||||||
| 
 | 
 | ||||||
| 				err = db.Save(&user).Error | 				err = db.Save(&user).Error | ||||||
| 				require.NoError(t, err) | 				require.NoError(t, err) | ||||||
| @ -340,9 +340,9 @@ func TestConstraints(t *testing.T) { | |||||||
| 			name: "allow-duplicate-username-oidc-then-cli", | 			name: "allow-duplicate-username-oidc-then-cli", | ||||||
| 			run: func(t *testing.T, db *gorm.DB) { | 			run: func(t *testing.T, db *gorm.DB) { | ||||||
| 				user := types.User{ | 				user := types.User{ | ||||||
| 					Name: "user1", | 					Name:               "user1", | ||||||
|  | 					ProviderIdentifier: sql.NullString{String: "http://test.com/user1", Valid: true}, | ||||||
| 				} | 				} | ||||||
| 				user.ProviderIdentifier.String = "http://test.com/user1" |  | ||||||
| 
 | 
 | ||||||
| 				err := db.Save(&user).Error | 				err := db.Save(&user).Error | ||||||
| 				require.NoError(t, err) | 				require.NoError(t, err) | ||||||
| @ -360,7 +360,7 @@ func TestConstraints(t *testing.T) { | |||||||
| 				t.Fatalf("creating database: %s", err) | 				t.Fatalf("creating database: %s", err) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			tt.run(t, db.DB) | 			tt.run(t, db.DB.Debug()) | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -27,7 +27,7 @@ type User struct { | |||||||
| 
 | 
 | ||||||
| 	// Username for the user, is used if email is empty
 | 	// Username for the user, is used if email is empty
 | ||||||
| 	// Should not be used, please use Username().
 | 	// Should not be used, please use Username().
 | ||||||
| 	Name string `gorm:"uniqueIndex:idx_name_provider_identifier;index"` | 	Name string | ||||||
| 
 | 
 | ||||||
| 	// Typically the full name of the user
 | 	// Typically the full name of the user
 | ||||||
| 	DisplayName string | 	DisplayName string | ||||||
| @ -39,7 +39,7 @@ type User struct { | |||||||
| 	// Unique identifier of the user from OIDC,
 | 	// Unique identifier of the user from OIDC,
 | ||||||
| 	// comes from `sub` claim in the OIDC token
 | 	// comes from `sub` claim in the OIDC token
 | ||||||
| 	// and is used to lookup the user.
 | 	// and is used to lookup the user.
 | ||||||
| 	ProviderIdentifier sql.NullString `gorm:"uniqueIndex:idx_name_provider_identifier;uniqueIndex:idx_provider_identifier"` | 	ProviderIdentifier sql.NullString | ||||||
| 
 | 
 | ||||||
| 	// Provider is the origin of the user account,
 | 	// Provider is the origin of the user account,
 | ||||||
| 	// same as RegistrationMethod, without authkey.
 | 	// same as RegistrationMethod, without authkey.
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user