[MM-54456] Fix potential read after write issue when loading license (#24524)
* Fix potential read after write issue when loading license * Use upsert
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c53b5f7b2b
Коммит
b4a47803e6
@@ -4,6 +4,8 @@
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
sq "github.com/mattermost/squirrel"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
@@ -23,46 +25,41 @@ func newSqlLicenseStore(sqlStore *SqlStore) store.LicenseStore {
|
||||
|
||||
// Save validates and stores the license instance in the database. The Id
|
||||
// and Bytes fields are mandatory. The Bytes field is limited to a maximum
|
||||
// of 10000 bytes. If the license ID matches an existing license in the
|
||||
// database it returns the license stored in the database. If not, it saves the
|
||||
// new database and returns the created license with the CreateAt field
|
||||
// updated.
|
||||
func (ls SqlLicenseStore) Save(license *model.LicenseRecord) (*model.LicenseRecord, error) {
|
||||
// of 10000 bytes. Provided license is saved only if missing.
|
||||
func (ls SqlLicenseStore) Save(license *model.LicenseRecord) error {
|
||||
license.PreSave()
|
||||
if err := license.IsValid(); err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
query := ls.getQueryBuilder().
|
||||
Select("Id, CreateAt, Bytes").
|
||||
From("Licenses").
|
||||
Where(sq.Eq{"Id": license.Id})
|
||||
Insert("Licenses").
|
||||
Columns("Id", "CreateAt", "Bytes").
|
||||
Values(license.Id, license.CreateAt, license.Bytes)
|
||||
|
||||
if ls.DriverName() == model.DatabaseDriverMysql {
|
||||
query = query.SuffixExpr(sq.Expr("ON DUPLICATE KEY UPDATE Id=Id"))
|
||||
} else {
|
||||
query = query.SuffixExpr(sq.Expr("ON CONFLICT (Id) DO NOTHING"))
|
||||
}
|
||||
|
||||
queryString, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "license_tosql")
|
||||
return errors.Wrap(err, "license_tosql")
|
||||
}
|
||||
var storedLicense model.LicenseRecord
|
||||
if err := ls.GetReplicaX().Get(&storedLicense, queryString, args...); err != nil {
|
||||
// Only insert if not exists
|
||||
query, args, err := ls.getQueryBuilder().
|
||||
Insert("Licenses").
|
||||
Columns("Id", "CreateAt", "Bytes").
|
||||
Values(license.Id, license.CreateAt, license.Bytes).
|
||||
ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "license_record_tosql")
|
||||
}
|
||||
if _, err := ls.GetMasterX().Exec(query, args...); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get License with licenseId=%s", license.Id)
|
||||
}
|
||||
return license, nil
|
||||
|
||||
if _, err := ls.GetMasterX().Exec(queryString, args...); err != nil {
|
||||
return errors.Wrapf(err, "failed to insert License with licenseId=%s", license.Id)
|
||||
}
|
||||
return &storedLicense, nil
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// Get obtains the license with the provided id parameter from the database.
|
||||
// If the license doesn't exist it returns a model.AppError with
|
||||
// http.StatusNotFound in the StatusCode field.
|
||||
func (ls SqlLicenseStore) Get(id string) (*model.LicenseRecord, error) {
|
||||
func (ls SqlLicenseStore) Get(ctx context.Context, id string) (*model.LicenseRecord, error) {
|
||||
query := ls.getQueryBuilder().
|
||||
Select("Id, CreateAt, Bytes").
|
||||
From("Licenses").
|
||||
@@ -74,7 +71,7 @@ func (ls SqlLicenseStore) Get(id string) (*model.LicenseRecord, error) {
|
||||
}
|
||||
|
||||
license := &model.LicenseRecord{}
|
||||
if err := ls.GetReplicaX().Get(license, queryString, args...); err != nil {
|
||||
if err := ls.DBXFromContext(ctx).Get(license, queryString, args...); err != nil {
|
||||
return nil, store.NewErrNotFound("License", id)
|
||||
}
|
||||
return license, nil
|
||||
|
||||
Ссылка в новой задаче
Block a user