code.gitea.io/gitea@v1.22.3/cmd/admin_auth_stmp.go (about)

     1  // Copyright 2023 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package cmd
     5  
     6  import (
     7  	"errors"
     8  	"strings"
     9  
    10  	auth_model "code.gitea.io/gitea/models/auth"
    11  	"code.gitea.io/gitea/modules/util"
    12  	"code.gitea.io/gitea/services/auth/source/smtp"
    13  
    14  	"github.com/urfave/cli/v2"
    15  )
    16  
    17  var (
    18  	smtpCLIFlags = []cli.Flag{
    19  		&cli.StringFlag{
    20  			Name:  "name",
    21  			Value: "",
    22  			Usage: "Application Name",
    23  		},
    24  		&cli.StringFlag{
    25  			Name:  "auth-type",
    26  			Value: "PLAIN",
    27  			Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
    28  		},
    29  		&cli.StringFlag{
    30  			Name:  "host",
    31  			Value: "",
    32  			Usage: "SMTP Host",
    33  		},
    34  		&cli.IntFlag{
    35  			Name:  "port",
    36  			Usage: "SMTP Port",
    37  		},
    38  		&cli.BoolFlag{
    39  			Name:  "force-smtps",
    40  			Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
    41  			Value: true,
    42  		},
    43  		&cli.BoolFlag{
    44  			Name:  "skip-verify",
    45  			Usage: "Skip TLS verify.",
    46  			Value: true,
    47  		},
    48  		&cli.StringFlag{
    49  			Name:  "helo-hostname",
    50  			Value: "",
    51  			Usage: "Hostname sent with HELO. Leave blank to send current hostname",
    52  		},
    53  		&cli.BoolFlag{
    54  			Name:  "disable-helo",
    55  			Usage: "Disable SMTP helo.",
    56  			Value: true,
    57  		},
    58  		&cli.StringFlag{
    59  			Name:  "allowed-domains",
    60  			Value: "",
    61  			Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')",
    62  		},
    63  		&cli.BoolFlag{
    64  			Name:  "skip-local-2fa",
    65  			Usage: "Skip 2FA to log on.",
    66  			Value: true,
    67  		},
    68  		&cli.BoolFlag{
    69  			Name:  "active",
    70  			Usage: "This Authentication Source is Activated.",
    71  			Value: true,
    72  		},
    73  	}
    74  
    75  	microcmdAuthAddSMTP = &cli.Command{
    76  		Name:   "add-smtp",
    77  		Usage:  "Add new SMTP authentication source",
    78  		Action: runAddSMTP,
    79  		Flags:  smtpCLIFlags,
    80  	}
    81  
    82  	microcmdAuthUpdateSMTP = &cli.Command{
    83  		Name:   "update-smtp",
    84  		Usage:  "Update existing SMTP authentication source",
    85  		Action: runUpdateSMTP,
    86  		Flags:  append(smtpCLIFlags[:1], append([]cli.Flag{idFlag}, smtpCLIFlags[1:]...)...),
    87  	}
    88  )
    89  
    90  func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
    91  	if c.IsSet("auth-type") {
    92  		conf.Auth = c.String("auth-type")
    93  		validAuthTypes := []string{"PLAIN", "LOGIN", "CRAM-MD5"}
    94  		if !util.SliceContainsString(validAuthTypes, strings.ToUpper(c.String("auth-type"))) {
    95  			return errors.New("Auth must be one of PLAIN/LOGIN/CRAM-MD5")
    96  		}
    97  		conf.Auth = c.String("auth-type")
    98  	}
    99  	if c.IsSet("host") {
   100  		conf.Host = c.String("host")
   101  	}
   102  	if c.IsSet("port") {
   103  		conf.Port = c.Int("port")
   104  	}
   105  	if c.IsSet("allowed-domains") {
   106  		conf.AllowedDomains = c.String("allowed-domains")
   107  	}
   108  	if c.IsSet("force-smtps") {
   109  		conf.ForceSMTPS = c.Bool("force-smtps")
   110  	}
   111  	if c.IsSet("skip-verify") {
   112  		conf.SkipVerify = c.Bool("skip-verify")
   113  	}
   114  	if c.IsSet("helo-hostname") {
   115  		conf.HeloHostname = c.String("helo-hostname")
   116  	}
   117  	if c.IsSet("disable-helo") {
   118  		conf.DisableHelo = c.Bool("disable-helo")
   119  	}
   120  	if c.IsSet("skip-local-2fa") {
   121  		conf.SkipLocalTwoFA = c.Bool("skip-local-2fa")
   122  	}
   123  	return nil
   124  }
   125  
   126  func runAddSMTP(c *cli.Context) error {
   127  	ctx, cancel := installSignals()
   128  	defer cancel()
   129  
   130  	if err := initDB(ctx); err != nil {
   131  		return err
   132  	}
   133  
   134  	if !c.IsSet("name") || len(c.String("name")) == 0 {
   135  		return errors.New("name must be set")
   136  	}
   137  	if !c.IsSet("host") || len(c.String("host")) == 0 {
   138  		return errors.New("host must be set")
   139  	}
   140  	if !c.IsSet("port") {
   141  		return errors.New("port must be set")
   142  	}
   143  	active := true
   144  	if c.IsSet("active") {
   145  		active = c.Bool("active")
   146  	}
   147  
   148  	var smtpConfig smtp.Source
   149  	if err := parseSMTPConfig(c, &smtpConfig); err != nil {
   150  		return err
   151  	}
   152  
   153  	// If not set default to PLAIN
   154  	if len(smtpConfig.Auth) == 0 {
   155  		smtpConfig.Auth = "PLAIN"
   156  	}
   157  
   158  	return auth_model.CreateSource(ctx, &auth_model.Source{
   159  		Type:     auth_model.SMTP,
   160  		Name:     c.String("name"),
   161  		IsActive: active,
   162  		Cfg:      &smtpConfig,
   163  	})
   164  }
   165  
   166  func runUpdateSMTP(c *cli.Context) error {
   167  	if !c.IsSet("id") {
   168  		return errors.New("--id flag is missing")
   169  	}
   170  
   171  	ctx, cancel := installSignals()
   172  	defer cancel()
   173  
   174  	if err := initDB(ctx); err != nil {
   175  		return err
   176  	}
   177  
   178  	source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
   179  	if err != nil {
   180  		return err
   181  	}
   182  
   183  	smtpConfig := source.Cfg.(*smtp.Source)
   184  
   185  	if err := parseSMTPConfig(c, smtpConfig); err != nil {
   186  		return err
   187  	}
   188  
   189  	if c.IsSet("name") {
   190  		source.Name = c.String("name")
   191  	}
   192  
   193  	if c.IsSet("active") {
   194  		source.IsActive = c.Bool("active")
   195  	}
   196  
   197  	source.Cfg = smtpConfig
   198  
   199  	return auth_model.UpdateSource(ctx, source)
   200  }