code.gitea.io/gitea@v1.21.7/models/migrations/v1_17/v223.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package v1_17 //nolint
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"code.gitea.io/gitea/models/migrations/base"
    11  	"code.gitea.io/gitea/modules/setting"
    12  	"code.gitea.io/gitea/modules/timeutil"
    13  
    14  	"xorm.io/xorm"
    15  )
    16  
    17  func RenameCredentialIDBytes(x *xorm.Engine) error {
    18  	// This migration maybe rerun so that we should check if it has been run
    19  	credentialIDExist, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id")
    20  	if err != nil {
    21  		return err
    22  	}
    23  	if credentialIDExist {
    24  		credentialIDBytesExists, err := x.Dialect().IsColumnExist(x.DB(), context.Background(), "webauthn_credential", "credential_id_bytes")
    25  		if err != nil {
    26  			return err
    27  		}
    28  		if !credentialIDBytesExists {
    29  			return nil
    30  		}
    31  	}
    32  
    33  	err = func() error {
    34  		// webauthnCredential table
    35  		type webauthnCredential struct {
    36  			ID        int64 `xorm:"pk autoincr"`
    37  			Name      string
    38  			LowerName string `xorm:"unique(s)"`
    39  			UserID    int64  `xorm:"INDEX unique(s)"`
    40  			// Note the lack of INDEX here
    41  			CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
    42  			PublicKey         []byte
    43  			AttestationType   string
    44  			AAGUID            []byte
    45  			SignCount         uint32 `xorm:"BIGINT"`
    46  			CloneWarning      bool
    47  			CreatedUnix       timeutil.TimeStamp `xorm:"INDEX created"`
    48  			UpdatedUnix       timeutil.TimeStamp `xorm:"INDEX updated"`
    49  		}
    50  		sess := x.NewSession()
    51  		defer sess.Close()
    52  		if err := sess.Begin(); err != nil {
    53  			return err
    54  		}
    55  
    56  		if err := sess.Sync(new(webauthnCredential)); err != nil {
    57  			return fmt.Errorf("error on Sync: %w", err)
    58  		}
    59  
    60  		if credentialIDExist {
    61  			// if both errors and message exist, drop message at first
    62  			if err := base.DropTableColumns(sess, "webauthn_credential", "credential_id"); err != nil {
    63  				return err
    64  			}
    65  		}
    66  
    67  		switch {
    68  		case setting.Database.Type.IsMySQL():
    69  			if _, err := sess.Exec("ALTER TABLE `webauthn_credential` CHANGE credential_id_bytes credential_id VARBINARY(1024)"); err != nil {
    70  				return err
    71  			}
    72  		case setting.Database.Type.IsMSSQL():
    73  			if _, err := sess.Exec("sp_rename 'webauthn_credential.credential_id_bytes', 'credential_id', 'COLUMN'"); err != nil {
    74  				return err
    75  			}
    76  		default:
    77  			if _, err := sess.Exec("ALTER TABLE `webauthn_credential` RENAME COLUMN credential_id_bytes TO credential_id"); err != nil {
    78  				return err
    79  			}
    80  		}
    81  		return sess.Commit()
    82  	}()
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	// Create webauthnCredential table
    88  	type webauthnCredential struct {
    89  		ID              int64 `xorm:"pk autoincr"`
    90  		Name            string
    91  		LowerName       string `xorm:"unique(s)"`
    92  		UserID          int64  `xorm:"INDEX unique(s)"`
    93  		CredentialID    []byte `xorm:"INDEX VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
    94  		PublicKey       []byte
    95  		AttestationType string
    96  		AAGUID          []byte
    97  		SignCount       uint32 `xorm:"BIGINT"`
    98  		CloneWarning    bool
    99  		CreatedUnix     timeutil.TimeStamp `xorm:"INDEX created"`
   100  		UpdatedUnix     timeutil.TimeStamp `xorm:"INDEX updated"`
   101  	}
   102  	return x.Sync(&webauthnCredential{})
   103  }