code.gitea.io/gitea@v1.21.7/models/secret/secret.go (about)

     1  // Copyright 2022 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package secret
     5  
     6  import (
     7  	"context"
     8  	"errors"
     9  	"fmt"
    10  	"strings"
    11  
    12  	"code.gitea.io/gitea/models/db"
    13  	secret_module "code.gitea.io/gitea/modules/secret"
    14  	"code.gitea.io/gitea/modules/setting"
    15  	"code.gitea.io/gitea/modules/timeutil"
    16  	"code.gitea.io/gitea/modules/util"
    17  
    18  	"xorm.io/builder"
    19  )
    20  
    21  // Secret represents a secret
    22  type Secret struct {
    23  	ID          int64
    24  	OwnerID     int64              `xorm:"INDEX UNIQUE(owner_repo_name) NOT NULL"`
    25  	RepoID      int64              `xorm:"INDEX UNIQUE(owner_repo_name) NOT NULL DEFAULT 0"`
    26  	Name        string             `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
    27  	Data        string             `xorm:"LONGTEXT"` // encrypted data
    28  	CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
    29  }
    30  
    31  // ErrSecretNotFound represents a "secret not found" error.
    32  type ErrSecretNotFound struct {
    33  	Name string
    34  }
    35  
    36  func (err ErrSecretNotFound) Error() string {
    37  	return fmt.Sprintf("secret was not found [name: %s]", err.Name)
    38  }
    39  
    40  func (err ErrSecretNotFound) Unwrap() error {
    41  	return util.ErrNotExist
    42  }
    43  
    44  // InsertEncryptedSecret Creates, encrypts, and validates a new secret with yet unencrypted data and insert into database
    45  func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, data string) (*Secret, error) {
    46  	encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	secret := &Secret{
    51  		OwnerID: ownerID,
    52  		RepoID:  repoID,
    53  		Name:    strings.ToUpper(name),
    54  		Data:    encrypted,
    55  	}
    56  	if err := secret.Validate(); err != nil {
    57  		return secret, err
    58  	}
    59  	return secret, db.Insert(ctx, secret)
    60  }
    61  
    62  func init() {
    63  	db.RegisterModel(new(Secret))
    64  }
    65  
    66  func (s *Secret) Validate() error {
    67  	if s.OwnerID == 0 && s.RepoID == 0 {
    68  		return errors.New("the secret is not bound to any scope")
    69  	}
    70  	return nil
    71  }
    72  
    73  type FindSecretsOptions struct {
    74  	db.ListOptions
    75  	OwnerID  int64
    76  	RepoID   int64
    77  	SecretID int64
    78  	Name     string
    79  }
    80  
    81  func (opts *FindSecretsOptions) toConds() builder.Cond {
    82  	cond := builder.NewCond()
    83  	if opts.OwnerID > 0 {
    84  		cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
    85  	}
    86  	if opts.RepoID > 0 {
    87  		cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
    88  	}
    89  	if opts.SecretID != 0 {
    90  		cond = cond.And(builder.Eq{"id": opts.SecretID})
    91  	}
    92  	if opts.Name != "" {
    93  		cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)})
    94  	}
    95  
    96  	return cond
    97  }
    98  
    99  func FindSecrets(ctx context.Context, opts FindSecretsOptions) ([]*Secret, error) {
   100  	var secrets []*Secret
   101  	sess := db.GetEngine(ctx)
   102  	if opts.PageSize != 0 {
   103  		sess = db.SetSessionPagination(sess, &opts.ListOptions)
   104  	}
   105  	return secrets, sess.
   106  		Where(opts.toConds()).
   107  		Find(&secrets)
   108  }
   109  
   110  // CountSecrets counts the secrets
   111  func CountSecrets(ctx context.Context, opts *FindSecretsOptions) (int64, error) {
   112  	return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Secret))
   113  }
   114  
   115  // UpdateSecret changes org or user reop secret.
   116  func UpdateSecret(ctx context.Context, secretID int64, data string) error {
   117  	encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
   118  	if err != nil {
   119  		return err
   120  	}
   121  
   122  	s := &Secret{
   123  		Data: encrypted,
   124  	}
   125  	affected, err := db.GetEngine(ctx).ID(secretID).Cols("data").Update(s)
   126  	if affected != 1 {
   127  		return ErrSecretNotFound{}
   128  	}
   129  	return err
   130  }