code.gitea.io/gitea@v1.21.7/models/migrations/v1_17/v221.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  	"encoding/base32"
     8  	"fmt"
     9  
    10  	"code.gitea.io/gitea/modules/timeutil"
    11  
    12  	"xorm.io/xorm"
    13  )
    14  
    15  func StoreWebauthnCredentialIDAsBytes(x *xorm.Engine) error {
    16  	// Create webauthnCredential table
    17  	type webauthnCredential struct {
    18  		ID           int64 `xorm:"pk autoincr"`
    19  		Name         string
    20  		LowerName    string `xorm:"unique(s)"`
    21  		UserID       int64  `xorm:"INDEX unique(s)"`
    22  		CredentialID string `xorm:"INDEX VARCHAR(410)"`
    23  		// Note the lack of INDEX here - these will be created once the column is renamed in v223.go
    24  		CredentialIDBytes []byte `xorm:"VARBINARY(1024)"` // CredentialID is at most 1023 bytes as per spec released 20 July 2022
    25  		PublicKey         []byte
    26  		AttestationType   string
    27  		AAGUID            []byte
    28  		SignCount         uint32 `xorm:"BIGINT"`
    29  		CloneWarning      bool
    30  		CreatedUnix       timeutil.TimeStamp `xorm:"INDEX created"`
    31  		UpdatedUnix       timeutil.TimeStamp `xorm:"INDEX updated"`
    32  	}
    33  	if err := x.Sync(&webauthnCredential{}); err != nil {
    34  		return err
    35  	}
    36  
    37  	var start int
    38  	creds := make([]*webauthnCredential, 0, 50)
    39  	for {
    40  		err := x.Select("id, credential_id").OrderBy("id").Limit(50, start).Find(&creds)
    41  		if err != nil {
    42  			return err
    43  		}
    44  
    45  		err = func() error {
    46  			sess := x.NewSession()
    47  			defer sess.Close()
    48  			if err := sess.Begin(); err != nil {
    49  				return fmt.Errorf("unable to allow start session. Error: %w", err)
    50  			}
    51  			for _, cred := range creds {
    52  				cred.CredentialIDBytes, err = base32.HexEncoding.DecodeString(cred.CredentialID)
    53  				if err != nil {
    54  					return fmt.Errorf("unable to parse credential id %s for credential[%d]: %w", cred.CredentialID, cred.ID, err)
    55  				}
    56  				count, err := sess.ID(cred.ID).Cols("credential_id_bytes").Update(cred)
    57  				if count != 1 || err != nil {
    58  					return fmt.Errorf("unable to update credential id bytes for credential[%d]: %d,%w", cred.ID, count, err)
    59  				}
    60  			}
    61  			return sess.Commit()
    62  		}()
    63  		if err != nil {
    64  			return err
    65  		}
    66  
    67  		if len(creds) < 50 {
    68  			break
    69  		}
    70  		start += 50
    71  		creds = creds[:0]
    72  	}
    73  	return nil
    74  }