mirror of
https://github.com/juanfont/headscale.git
synced 2026-11-04 04:34:07 +09:00
db, types: add a credentials column for keys a token made
No released version made keys from tokens, so existing rows stay false.
This commit is contained in:
1 parent
f838b0ab2d
commit
7d8d875c80
8 files changed
+137
-87
No files matched your search
+14
-13
@@ -39,19 +39,20 @@ func credentialToOAuthClient(c *types.Credential) *types.OAuthClient {
|
|||||||
// the User association is carried through when preloaded.
|
// the User association is carried through when preloaded.
|
||||||
func credentialToPreAuthKey(c *types.Credential) *types.PreAuthKey {
|
func credentialToPreAuthKey(c *types.Credential) *types.PreAuthKey {
|
||||||
return &types.PreAuthKey{
|
return &types.PreAuthKey{
|
||||||
ID: c.ID,
|
ID: c.ID,
|
||||||
Prefix: c.Identifier,
|
Prefix: c.Identifier,
|
||||||
Hash: c.Hash,
|
Hash: c.Hash,
|
||||||
UserID: c.UserID,
|
UserID: c.UserID,
|
||||||
User: c.User,
|
User: c.User,
|
||||||
Description: c.Description,
|
Description: c.Description,
|
||||||
Reusable: c.Reusable,
|
Reusable: c.Reusable,
|
||||||
Ephemeral: c.Ephemeral,
|
Ephemeral: c.Ephemeral,
|
||||||
Used: c.Used,
|
Used: c.Used,
|
||||||
Tags: c.Tags,
|
Tags: c.Tags,
|
||||||
CreatedAt: c.CreatedAt,
|
CreatedByToken: c.CreatedByToken,
|
||||||
Expiration: c.Expiration,
|
CreatedAt: c.CreatedAt,
|
||||||
Revoked: c.Revoked,
|
Expiration: c.Expiration,
|
||||||
|
Revoked: c.Revoked,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -331,6 +331,33 @@ WHERE auth_key_id IN (
|
|||||||
},
|
},
|
||||||
Rollback: func(db *gorm.DB) error { return nil },
|
Rollback: func(db *gorm.DB) error { return nil },
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Mark the auth keys an OAuth access token makes. A database
|
||||||
|
// that got the credentials table from the DDL above already
|
||||||
|
// has the column; no released version made keys from tokens,
|
||||||
|
// so existing rows stay false.
|
||||||
|
ID: "202610221200-credential-created-by-token",
|
||||||
|
Migrate: func(tx *gorm.DB) error {
|
||||||
|
return tx.Transaction(func(tx *gorm.DB) error {
|
||||||
|
if tx.Migrator().HasColumn(&types.Credential{}, "created_by_token") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
colType := "numeric"
|
||||||
|
if tx.Name() != sqlite.DriverName {
|
||||||
|
colType = "boolean"
|
||||||
|
}
|
||||||
|
|
||||||
|
err := tx.Exec(`ALTER TABLE credentials ADD COLUMN created_by_token ` + colType + ` DEFAULT false`).Error
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("adding created_by_token to credentials: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Rollback: func(db *gorm.DB) error { return nil },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ const credentialsDDLSQLite = `CREATE TABLE credentials(
|
|||||||
created_at datetime,
|
created_at datetime,
|
||||||
expiration datetime,
|
expiration datetime,
|
||||||
revoked datetime,
|
revoked datetime,
|
||||||
|
created_by_token numeric DEFAULT false,
|
||||||
|
|
||||||
CONSTRAINT fk_credentials_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL,
|
CONSTRAINT fk_credentials_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
CONSTRAINT chk_credentials_hash CHECK(hash IS NOT NULL OR revoked IS NOT NULL),
|
CONSTRAINT chk_credentials_hash CHECK(hash IS NOT NULL OR revoked IS NOT NULL),
|
||||||
@@ -59,6 +60,7 @@ const credentialsDDLPostgres = `CREATE TABLE credentials(
|
|||||||
created_at timestamptz,
|
created_at timestamptz,
|
||||||
expiration timestamptz,
|
expiration timestamptz,
|
||||||
revoked timestamptz,
|
revoked timestamptz,
|
||||||
|
created_by_token boolean DEFAULT false,
|
||||||
|
|
||||||
CONSTRAINT fk_credentials_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL,
|
CONSTRAINT fk_credentials_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
CONSTRAINT chk_credentials_hash CHECK(hash IS NOT NULL OR revoked IS NOT NULL),
|
CONSTRAINT chk_credentials_hash CHECK(hash IS NOT NULL OR revoked IS NOT NULL),
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ CREATE TABLE credentials(
|
|||||||
created_at datetime,
|
created_at datetime,
|
||||||
expiration datetime,
|
expiration datetime,
|
||||||
revoked datetime,
|
revoked datetime,
|
||||||
|
created_by_token numeric DEFAULT false,
|
||||||
|
|
||||||
CONSTRAINT fk_credentials_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL,
|
CONSTRAINT fk_credentials_user FOREIGN KEY(user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||||||
CONSTRAINT chk_credentials_hash CHECK(hash IS NOT NULL OR revoked IS NOT NULL),
|
CONSTRAINT chk_credentials_hash CHECK(hash IS NOT NULL OR revoked IS NOT NULL),
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ type Credential struct {
|
|||||||
// the Identifier of its issuing OAuth client.
|
// the Identifier of its issuing OAuth client.
|
||||||
ClientID string
|
ClientID string
|
||||||
|
|
||||||
|
// CreatedByToken marks a pre-auth key an OAuth access token made: a token
|
||||||
|
// lists those without all=true.
|
||||||
|
CreatedByToken bool `gorm:"default:false"`
|
||||||
|
|
||||||
CreatedAt *time.Time
|
CreatedAt *time.Time
|
||||||
Expiration *time.Time
|
Expiration *time.Time
|
||||||
Revoked *time.Time
|
Revoked *time.Time
|
||||||
@@ -72,19 +76,20 @@ func (pak *PreAuthKey) AsCredential() *Credential {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Credential{
|
return &Credential{
|
||||||
ID: pak.ID,
|
ID: pak.ID,
|
||||||
Kind: CredentialPreAuthKey,
|
Kind: CredentialPreAuthKey,
|
||||||
Identifier: pak.Prefix,
|
Identifier: pak.Prefix,
|
||||||
Hash: pak.Hash,
|
Hash: pak.Hash,
|
||||||
UserID: pak.UserID,
|
UserID: pak.UserID,
|
||||||
User: pak.User,
|
User: pak.User,
|
||||||
Description: pak.Description,
|
Description: pak.Description,
|
||||||
Reusable: pak.Reusable,
|
Reusable: pak.Reusable,
|
||||||
Ephemeral: pak.Ephemeral,
|
Ephemeral: pak.Ephemeral,
|
||||||
Used: pak.Used,
|
Used: pak.Used,
|
||||||
Tags: pak.Tags,
|
Tags: pak.Tags,
|
||||||
CreatedAt: pak.CreatedAt,
|
CreatedByToken: pak.CreatedByToken,
|
||||||
Expiration: pak.Expiration,
|
CreatedAt: pak.CreatedAt,
|
||||||
Revoked: pak.Revoked,
|
Expiration: pak.Expiration,
|
||||||
|
Revoked: pak.Revoked,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,6 +65,9 @@ type PreAuthKey struct {
|
|||||||
// If non-empty, this creates tagged nodes (not user-owned).
|
// If non-empty, this creates tagged nodes (not user-owned).
|
||||||
Tags []string `gorm:"serializer:json"`
|
Tags []string `gorm:"serializer:json"`
|
||||||
|
|
||||||
|
// CreatedByToken is set when an OAuth access token made the key.
|
||||||
|
CreatedByToken bool
|
||||||
|
|
||||||
CreatedAt *time.Time
|
CreatedAt *time.Time
|
||||||
Expiration *time.Time
|
Expiration *time.Time
|
||||||
|
|
||||||
|
|||||||
@@ -144,19 +144,20 @@ func (src *PreAuthKey) Clone() *PreAuthKey {
|
|||||||
|
|
||||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||||
var _PreAuthKeyCloneNeedsRegeneration = PreAuthKey(struct {
|
var _PreAuthKeyCloneNeedsRegeneration = PreAuthKey(struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
Prefix string
|
Prefix string
|
||||||
Hash []byte
|
Hash []byte
|
||||||
UserID *uint
|
UserID *uint
|
||||||
User *User
|
User *User
|
||||||
Description string
|
Description string
|
||||||
Reusable bool
|
Reusable bool
|
||||||
Ephemeral bool
|
Ephemeral bool
|
||||||
Used bool
|
Used bool
|
||||||
Tags []string
|
Tags []string
|
||||||
CreatedAt *time.Time
|
CreatedByToken bool
|
||||||
Expiration *time.Time
|
CreatedAt *time.Time
|
||||||
Revoked *time.Time
|
Expiration *time.Time
|
||||||
|
Revoked *time.Time
|
||||||
}{})
|
}{})
|
||||||
|
|
||||||
// Clone makes a deep copy of Credential.
|
// Clone makes a deep copy of Credential.
|
||||||
@@ -193,21 +194,22 @@ func (src *Credential) Clone() *Credential {
|
|||||||
|
|
||||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||||
var _CredentialCloneNeedsRegeneration = Credential(struct {
|
var _CredentialCloneNeedsRegeneration = Credential(struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
Kind CredentialKind
|
Kind CredentialKind
|
||||||
Identifier string
|
Identifier string
|
||||||
Hash []byte
|
Hash []byte
|
||||||
UserID *uint
|
UserID *uint
|
||||||
User *User
|
User *User
|
||||||
Description string
|
Description string
|
||||||
Scopes []string
|
Scopes []string
|
||||||
Tags []string
|
Tags []string
|
||||||
Reusable bool
|
Reusable bool
|
||||||
Ephemeral bool
|
Ephemeral bool
|
||||||
Used bool
|
Used bool
|
||||||
LastSeen *time.Time
|
LastSeen *time.Time
|
||||||
ClientID string
|
ClientID string
|
||||||
CreatedAt *time.Time
|
CreatedByToken bool
|
||||||
Expiration *time.Time
|
CreatedAt *time.Time
|
||||||
Revoked *time.Time
|
Expiration *time.Time
|
||||||
|
Revoked *time.Time
|
||||||
}{})
|
}{})
|
||||||
@@ -425,6 +425,9 @@ func (v PreAuthKeyView) Used() bool { return v.ж.Used }
|
|||||||
// Tags are copied to the node during registration.
|
// Tags are copied to the node during registration.
|
||||||
// If non-empty, this creates tagged nodes (not user-owned).
|
// If non-empty, this creates tagged nodes (not user-owned).
|
||||||
func (v PreAuthKeyView) Tags() views.Slice[string] { return views.SliceOf(v.ж.Tags) }
|
func (v PreAuthKeyView) Tags() views.Slice[string] { return views.SliceOf(v.ж.Tags) }
|
||||||
|
|
||||||
|
// CreatedByToken is set when an OAuth access token made the key.
|
||||||
|
func (v PreAuthKeyView) CreatedByToken() bool { return v.ж.CreatedByToken }
|
||||||
func (v PreAuthKeyView) CreatedAt() views.ValuePointer[time.Time] {
|
func (v PreAuthKeyView) CreatedAt() views.ValuePointer[time.Time] {
|
||||||
return views.ValuePointerOf(v.ж.CreatedAt)
|
return views.ValuePointerOf(v.ж.CreatedAt)
|
||||||
}
|
}
|
||||||
@@ -442,19 +445,20 @@ func (v PreAuthKeyView) Revoked() views.ValuePointer[time.Time] {
|
|||||||
|
|
||||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||||
var _PreAuthKeyViewNeedsRegeneration = PreAuthKey(struct {
|
var _PreAuthKeyViewNeedsRegeneration = PreAuthKey(struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
Prefix string
|
Prefix string
|
||||||
Hash []byte
|
Hash []byte
|
||||||
UserID *uint
|
UserID *uint
|
||||||
User *User
|
User *User
|
||||||
Description string
|
Description string
|
||||||
Reusable bool
|
Reusable bool
|
||||||
Ephemeral bool
|
Ephemeral bool
|
||||||
Used bool
|
Used bool
|
||||||
Tags []string
|
Tags []string
|
||||||
CreatedAt *time.Time
|
CreatedByToken bool
|
||||||
Expiration *time.Time
|
CreatedAt *time.Time
|
||||||
Revoked *time.Time
|
Expiration *time.Time
|
||||||
|
Revoked *time.Time
|
||||||
}{})
|
}{})
|
||||||
|
|
||||||
// View returns a read-only view of Credential.
|
// View returns a read-only view of Credential.
|
||||||
@@ -547,6 +551,10 @@ func (v CredentialView) LastSeen() views.ValuePointer[time.Time] {
|
|||||||
// ClientID links an OAuth access token (Kind == CredentialOAuthToken) back to
|
// ClientID links an OAuth access token (Kind == CredentialOAuthToken) back to
|
||||||
// the Identifier of its issuing OAuth client.
|
// the Identifier of its issuing OAuth client.
|
||||||
func (v CredentialView) ClientID() string { return v.ж.ClientID }
|
func (v CredentialView) ClientID() string { return v.ж.ClientID }
|
||||||
|
|
||||||
|
// CreatedByToken marks a pre-auth key an OAuth access token made: a token
|
||||||
|
// lists those without all=true.
|
||||||
|
func (v CredentialView) CreatedByToken() bool { return v.ж.CreatedByToken }
|
||||||
func (v CredentialView) CreatedAt() views.ValuePointer[time.Time] {
|
func (v CredentialView) CreatedAt() views.ValuePointer[time.Time] {
|
||||||
return views.ValuePointerOf(v.ж.CreatedAt)
|
return views.ValuePointerOf(v.ж.CreatedAt)
|
||||||
}
|
}
|
||||||
@@ -561,21 +569,22 @@ func (v CredentialView) Revoked() views.ValuePointer[time.Time] {
|
|||||||
|
|
||||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||||
var _CredentialViewNeedsRegeneration = Credential(struct {
|
var _CredentialViewNeedsRegeneration = Credential(struct {
|
||||||
ID uint64
|
ID uint64
|
||||||
Kind CredentialKind
|
Kind CredentialKind
|
||||||
Identifier string
|
Identifier string
|
||||||
Hash []byte
|
Hash []byte
|
||||||
UserID *uint
|
UserID *uint
|
||||||
User *User
|
User *User
|
||||||
Description string
|
Description string
|
||||||
Scopes []string
|
Scopes []string
|
||||||
Tags []string
|
Tags []string
|
||||||
Reusable bool
|
Reusable bool
|
||||||
Ephemeral bool
|
Ephemeral bool
|
||||||
Used bool
|
Used bool
|
||||||
LastSeen *time.Time
|
LastSeen *time.Time
|
||||||
ClientID string
|
ClientID string
|
||||||
CreatedAt *time.Time
|
CreatedByToken bool
|
||||||
Expiration *time.Time
|
CreatedAt *time.Time
|
||||||
Revoked *time.Time
|
Expiration *time.Time
|
||||||
|
Revoked *time.Time
|
||||||
}{})
|
}{})
|
||||||
Reference in new issue
Block a user