code.gitea.io/gitea@v1.21.7/models/migrations/v1_16/v189.go (about)

     1  // Copyright 2021 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package v1_16 //nolint
     5  
     6  import (
     7  	"encoding/binary"
     8  	"fmt"
     9  
    10  	"code.gitea.io/gitea/models/migrations/base"
    11  	"code.gitea.io/gitea/modules/json"
    12  
    13  	"xorm.io/xorm"
    14  )
    15  
    16  func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
    17  	jsonUnmarshalHandleDoubleEncode := func(bs []byte, v any) error {
    18  		err := json.Unmarshal(bs, v)
    19  		if err != nil {
    20  			ok := true
    21  			rs := []byte{}
    22  			temp := make([]byte, 2)
    23  			for _, rn := range string(bs) {
    24  				if rn > 0xffff {
    25  					ok = false
    26  					break
    27  				}
    28  				binary.LittleEndian.PutUint16(temp, uint16(rn))
    29  				rs = append(rs, temp...)
    30  			}
    31  			if ok {
    32  				if rs[0] == 0xff && rs[1] == 0xfe {
    33  					rs = rs[2:]
    34  				}
    35  				err = json.Unmarshal(rs, v)
    36  			}
    37  		}
    38  		if err != nil && len(bs) > 2 && bs[0] == 0xff && bs[1] == 0xfe {
    39  			err = json.Unmarshal(bs[2:], v)
    40  		}
    41  		return err
    42  	}
    43  
    44  	// LoginSource represents an external way for authorizing users.
    45  	type LoginSource struct {
    46  		ID        int64 `xorm:"pk autoincr"`
    47  		Type      int
    48  		IsActived bool   `xorm:"INDEX NOT NULL DEFAULT false"`
    49  		IsActive  bool   `xorm:"INDEX NOT NULL DEFAULT false"`
    50  		Cfg       string `xorm:"TEXT"`
    51  	}
    52  
    53  	const ldapType = 2
    54  	const dldapType = 5
    55  
    56  	type WrappedSource struct {
    57  		Source map[string]any
    58  	}
    59  
    60  	// change lower_email as unique
    61  	if err := x.Sync(new(LoginSource)); err != nil {
    62  		return err
    63  	}
    64  
    65  	sess := x.NewSession()
    66  	defer sess.Close()
    67  
    68  	const batchSize = 100
    69  	for start := 0; ; start += batchSize {
    70  		sources := make([]*LoginSource, 0, batchSize)
    71  		if err := sess.Limit(batchSize, start).Where("`type` = ? OR `type` = ?", ldapType, dldapType).Find(&sources); err != nil {
    72  			return err
    73  		}
    74  		if len(sources) == 0 {
    75  			break
    76  		}
    77  
    78  		for _, source := range sources {
    79  			wrapped := &WrappedSource{
    80  				Source: map[string]any{},
    81  			}
    82  			err := jsonUnmarshalHandleDoubleEncode([]byte(source.Cfg), &wrapped)
    83  			if err != nil {
    84  				return fmt.Errorf("failed to unmarshal %s: %w", source.Cfg, err)
    85  			}
    86  			if wrapped.Source != nil && len(wrapped.Source) > 0 {
    87  				bs, err := json.Marshal(wrapped.Source)
    88  				if err != nil {
    89  					return err
    90  				}
    91  				source.Cfg = string(bs)
    92  				if _, err := sess.ID(source.ID).Cols("cfg").Update(source); err != nil {
    93  					return err
    94  				}
    95  			}
    96  		}
    97  	}
    98  
    99  	if _, err := x.SetExpr("is_active", "is_actived").Update(&LoginSource{}); err != nil {
   100  		return fmt.Errorf("SetExpr Update failed:  %w", err)
   101  	}
   102  
   103  	if err := sess.Begin(); err != nil {
   104  		return err
   105  	}
   106  	if err := base.DropTableColumns(sess, "login_source", "is_actived"); err != nil {
   107  		return err
   108  	}
   109  
   110  	return sess.Commit()
   111  }