2016-08-14 07:11:52 +08:00
// Copyright 2016 The Gogs Authors. All rights reserved.
2016-12-21 20:13:17 +08:00
// Copyright 2016 The Gitea Authors. All rights reserved.
2022-11-28 02:20:29 +08:00
// SPDX-License-Identifier: MIT
2016-08-14 07:11:52 +08:00
package cmd
import (
2018-10-31 05:34:25 +08:00
"errors"
2016-08-14 07:11:52 +08:00
"fmt"
2018-09-12 22:46:02 +08:00
"os"
2020-12-17 15:57:32 +08:00
"strings"
2018-09-12 22:46:02 +08:00
"text/tabwriter"
2016-08-14 07:11:52 +08:00
2021-12-10 16:14:24 +08:00
asymkey_model "code.gitea.io/gitea/models/asymkey"
2022-08-25 10:31:57 +08:00
auth_model "code.gitea.io/gitea/models/auth"
2021-09-24 19:32:56 +08:00
"code.gitea.io/gitea/models/db"
2022-06-06 16:01:49 +08:00
repo_model "code.gitea.io/gitea/models/repo"
2019-03-27 17:33:00 +08:00
"code.gitea.io/gitea/modules/git"
2020-01-21 04:01:19 +08:00
"code.gitea.io/gitea/modules/graceful"
2017-12-31 22:45:46 +08:00
"code.gitea.io/gitea/modules/log"
2020-01-21 04:01:19 +08:00
repo_module "code.gitea.io/gitea/modules/repository"
2022-04-30 03:38:11 +08:00
"code.gitea.io/gitea/modules/util"
2021-09-24 19:32:56 +08:00
auth_service "code.gitea.io/gitea/services/auth"
2021-07-24 18:16:34 +08:00
"code.gitea.io/gitea/services/auth/source/oauth2"
2022-01-13 06:54:53 +08:00
"code.gitea.io/gitea/services/auth/source/smtp"
2021-11-17 23:17:31 +08:00
repo_service "code.gitea.io/gitea/services/repository"
2017-04-12 15:44:54 +08:00
"github.com/urfave/cli"
2016-08-14 07:11:52 +08:00
)
var (
2016-11-04 19:42:18 +08:00
// CmdAdmin represents the available admin sub-command.
2016-08-14 07:11:52 +08:00
CmdAdmin = cli . Command {
Name : "admin" ,
2018-01-13 06:16:49 +08:00
Usage : "Command line interface to perform common administrative operations" ,
2016-08-14 07:11:52 +08:00
Subcommands : [ ] cli . Command {
2020-10-16 10:48:38 +08:00
subcmdUser ,
2017-12-31 22:45:46 +08:00
subcmdRepoSyncReleases ,
2018-05-17 09:35:07 +08:00
subcmdRegenerate ,
2018-09-12 22:46:02 +08:00
subcmdAuth ,
2020-10-25 04:38:14 +08:00
subcmdSendMail ,
2016-08-14 07:11:52 +08:00
} ,
}
2017-12-31 22:45:46 +08:00
subcmdRepoSyncReleases = cli . Command {
Name : "repo-sync-releases" ,
Usage : "Synchronize repository releases with tags" ,
Action : runRepoSyncReleases ,
}
2018-05-17 09:35:07 +08:00
subcmdRegenerate = cli . Command {
Name : "regenerate" ,
Usage : "Regenerate specific files" ,
Subcommands : [ ] cli . Command {
microcmdRegenHooks ,
microcmdRegenKeys ,
} ,
}
microcmdRegenHooks = cli . Command {
Name : "hooks" ,
Usage : "Regenerate git-hooks" ,
Action : runRegenerateHooks ,
}
microcmdRegenKeys = cli . Command {
Name : "keys" ,
Usage : "Regenerate authorized_keys file" ,
Action : runRegenerateKeys ,
}
2018-09-12 22:46:02 +08:00
subcmdAuth = cli . Command {
Name : "auth" ,
Usage : "Modify external auth providers" ,
Subcommands : [ ] cli . Command {
microcmdAuthAddOauth ,
microcmdAuthUpdateOauth ,
2019-06-18 02:32:20 +08:00
cmdAuthAddLdapBindDn ,
cmdAuthUpdateLdapBindDn ,
cmdAuthAddLdapSimpleAuth ,
cmdAuthUpdateLdapSimpleAuth ,
2022-01-13 06:54:53 +08:00
microcmdAuthAddSMTP ,
microcmdAuthUpdateSMTP ,
2018-09-12 22:46:02 +08:00
microcmdAuthList ,
microcmdAuthDelete ,
} ,
}
microcmdAuthList = cli . Command {
Name : "list" ,
Usage : "List auth sources" ,
Action : runListAuth ,
2020-03-28 05:26:43 +08:00
Flags : [ ] cli . Flag {
cli . IntFlag {
Name : "min-width" ,
Usage : "Minimal cell width including any padding for the formatted table" ,
Value : 0 ,
} ,
cli . IntFlag {
Name : "tab-width" ,
Usage : "width of tab characters in formatted table (equivalent number of spaces)" ,
Value : 8 ,
} ,
cli . IntFlag {
Name : "padding" ,
Usage : "padding added to a cell before computing its width" ,
Value : 1 ,
} ,
cli . StringFlag {
Name : "pad-char" ,
Usage : ` ASCII char used for padding if padchar == '\\t', the Writer will assume that the width of a '\\t' in the formatted output is tabwidth, and cells are left-aligned independent of align_left (for correct-looking results, tabwidth must correspond to the tab width in the viewer displaying the result) ` ,
Value : "\t" ,
} ,
cli . BoolFlag {
Name : "vertical-bars" ,
Usage : "Set to true to print vertical bars between columns" ,
} ,
} ,
2018-09-12 22:46:02 +08:00
}
idFlag = cli . Int64Flag {
Name : "id" ,
2019-06-18 02:32:20 +08:00
Usage : "ID of authentication source" ,
2018-09-12 22:46:02 +08:00
}
microcmdAuthDelete = cli . Command {
Name : "delete" ,
Usage : "Delete specific auth source" ,
2020-01-08 07:41:16 +08:00
Flags : [ ] cli . Flag { idFlag } ,
2018-09-12 22:46:02 +08:00
Action : runDeleteAuth ,
}
oauthCLIFlags = [ ] cli . Flag {
cli . StringFlag {
Name : "name" ,
Value : "" ,
Usage : "Application Name" ,
} ,
cli . StringFlag {
Name : "provider" ,
Value : "" ,
Usage : "OAuth2 Provider" ,
} ,
cli . StringFlag {
Name : "key" ,
Value : "" ,
Usage : "Client ID (Key)" ,
} ,
cli . StringFlag {
Name : "secret" ,
Value : "" ,
Usage : "Client Secret" ,
} ,
cli . StringFlag {
Name : "auto-discover-url" ,
Value : "" ,
Usage : "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)" ,
} ,
cli . StringFlag {
Name : "use-custom-urls" ,
Value : "false" ,
Usage : "Use custom URLs for GitLab/GitHub OAuth endpoints" ,
} ,
2023-02-06 12:12:13 +08:00
cli . StringFlag {
Name : "custom-tenant-id" ,
Value : "" ,
Usage : "Use custom Tenant ID for OAuth endpoints" ,
} ,
2018-09-12 22:46:02 +08:00
cli . StringFlag {
Name : "custom-auth-url" ,
Value : "" ,
Usage : "Use a custom Authorization URL (option for GitLab/GitHub)" ,
} ,
cli . StringFlag {
Name : "custom-token-url" ,
Value : "" ,
Usage : "Use a custom Token URL (option for GitLab/GitHub)" ,
} ,
cli . StringFlag {
Name : "custom-profile-url" ,
Value : "" ,
Usage : "Use a custom Profile URL (option for GitLab/GitHub)" ,
} ,
cli . StringFlag {
Name : "custom-email-url" ,
Value : "" ,
Usage : "Use a custom Email URL (option for GitHub)" ,
} ,
2020-12-28 16:39:12 +08:00
cli . StringFlag {
Name : "icon-url" ,
Value : "" ,
Usage : "Custom icon URL for OAuth2 login source" ,
} ,
2021-09-11 00:37:57 +08:00
cli . BoolFlag {
Name : "skip-local-2fa" ,
Usage : "Set to true to skip local 2fa for users authenticated by this source" ,
} ,
2021-12-14 16:37:11 +08:00
cli . StringSliceFlag {
Name : "scopes" ,
Value : nil ,
Usage : "Scopes to request when to authenticate against this OAuth2 source" ,
} ,
cli . StringFlag {
Name : "required-claim-name" ,
Value : "" ,
Usage : "Claim name that has to be set to allow users to login with this source" ,
} ,
cli . StringFlag {
Name : "required-claim-value" ,
Value : "" ,
Usage : "Claim value that has to be set to allow users to login with this source" ,
} ,
cli . StringFlag {
Name : "group-claim-name" ,
Value : "" ,
Usage : "Claim name providing group names for this source" ,
} ,
cli . StringFlag {
Name : "admin-group" ,
Value : "" ,
Usage : "Group Claim value for administrator users" ,
} ,
cli . StringFlag {
Name : "restricted-group" ,
Value : "" ,
Usage : "Group Claim value for restricted users" ,
} ,
2023-02-08 14:44:42 +08:00
cli . StringFlag {
Name : "group-team-map" ,
Value : "" ,
Usage : "JSON mapping between groups and org teams" ,
} ,
cli . BoolFlag {
Name : "group-team-map-removal" ,
Usage : "Activate automatic team membership removal depending on groups" ,
} ,
2018-09-12 22:46:02 +08:00
}
microcmdAuthUpdateOauth = cli . Command {
Name : "update-oauth" ,
Usage : "Update existing Oauth authentication source" ,
Action : runUpdateOauth ,
Flags : append ( oauthCLIFlags [ : 1 ] , append ( [ ] cli . Flag { idFlag } , oauthCLIFlags [ 1 : ] ... ) ... ) ,
}
microcmdAuthAddOauth = cli . Command {
Name : "add-oauth" ,
Usage : "Add new Oauth authentication source" ,
Action : runAddOauth ,
Flags : oauthCLIFlags ,
}
2020-10-25 04:38:14 +08:00
subcmdSendMail = cli . Command {
Name : "sendmail" ,
Usage : "Send a message to all users" ,
Action : runSendMail ,
Flags : [ ] cli . Flag {
cli . StringFlag {
Name : "title" ,
Usage : ` a title of a message ` ,
Value : "" ,
} ,
cli . StringFlag {
Name : "content" ,
Usage : "a content of a message" ,
Value : "" ,
} ,
cli . BoolFlag {
Name : "force,f" ,
Usage : "A flag to bypass a confirmation step" ,
} ,
} ,
}
2022-01-13 06:54:53 +08:00
smtpCLIFlags = [ ] cli . Flag {
cli . StringFlag {
Name : "name" ,
Value : "" ,
Usage : "Application Name" ,
} ,
cli . StringFlag {
Name : "auth-type" ,
Value : "PLAIN" ,
Usage : "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN" ,
} ,
cli . StringFlag {
2022-11-11 05:12:23 +08:00
Name : "host" ,
2022-01-13 06:54:53 +08:00
Value : "" ,
2022-11-11 05:12:23 +08:00
Usage : "SMTP Host" ,
2022-01-13 06:54:53 +08:00
} ,
cli . IntFlag {
Name : "port" ,
Usage : "SMTP Port" ,
} ,
cli . BoolTFlag {
Name : "force-smtps" ,
Usage : "SMTPS is always used on port 465. Set this to force SMTPS on other ports." ,
} ,
cli . BoolTFlag {
Name : "skip-verify" ,
Usage : "Skip TLS verify." ,
} ,
cli . StringFlag {
Name : "helo-hostname" ,
Value : "" ,
Usage : "Hostname sent with HELO. Leave blank to send current hostname" ,
} ,
cli . BoolTFlag {
Name : "disable-helo" ,
Usage : "Disable SMTP helo." ,
} ,
cli . StringFlag {
Name : "allowed-domains" ,
Value : "" ,
Usage : "Leave empty to allow all domains. Separate multiple domains with a comma (',')" ,
} ,
cli . BoolTFlag {
Name : "skip-local-2fa" ,
Usage : "Skip 2FA to log on." ,
} ,
cli . BoolTFlag {
Name : "active" ,
Usage : "This Authentication Source is Activated." ,
} ,
}
microcmdAuthAddSMTP = cli . Command {
Name : "add-smtp" ,
Usage : "Add new SMTP authentication source" ,
Action : runAddSMTP ,
Flags : smtpCLIFlags ,
}
microcmdAuthUpdateSMTP = cli . Command {
Name : "update-smtp" ,
Usage : "Update existing SMTP authentication source" ,
Action : runUpdateSMTP ,
Flags : append ( smtpCLIFlags [ : 1 ] , append ( [ ] cli . Flag { idFlag } , smtpCLIFlags [ 1 : ] ... ) ... ) ,
}
2016-08-14 07:11:52 +08:00
)
2021-04-09 15:40:34 +08:00
func runRepoSyncReleases ( _ * cli . Context ) error {
2021-11-07 11:11:27 +08:00
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
2018-01-13 06:16:49 +08:00
return err
2017-12-31 22:45:46 +08:00
}
log . Trace ( "Synchronizing repository releases (this may take a while)" )
for page := 1 ; ; page ++ {
2022-11-19 16:12:33 +08:00
repos , count , err := repo_model . SearchRepositoryByName ( ctx , & repo_model . SearchRepoOptions {
2021-09-24 19:32:56 +08:00
ListOptions : db . ListOptions {
2022-06-06 16:01:49 +08:00
PageSize : repo_model . RepositoryListDefaultPageSize ,
2020-01-25 03:00:29 +08:00
Page : page ,
} ,
Private : true ,
2017-12-31 22:45:46 +08:00
} )
if err != nil {
2022-10-25 03:29:17 +08:00
return fmt . Errorf ( "SearchRepositoryByName: %w" , err )
2017-12-31 22:45:46 +08:00
}
if len ( repos ) == 0 {
break
}
log . Trace ( "Processing next %d repos of %d" , len ( repos ) , count )
for _ , repo := range repos {
log . Trace ( "Synchronizing repo %s with path %s" , repo . FullName ( ) , repo . RepoPath ( ) )
2022-03-30 03:13:41 +08:00
gitRepo , err := git . OpenRepository ( ctx , repo . RepoPath ( ) )
2017-12-31 22:45:46 +08:00
if err != nil {
log . Warn ( "OpenRepository: %v" , err )
continue
}
2018-01-13 06:16:49 +08:00
oldnum , err := getReleaseCount ( repo . ID )
2017-12-31 22:45:46 +08:00
if err != nil {
log . Warn ( " GetReleaseCountByRepoID: %v" , err )
}
log . Trace ( " currentNumReleases is %d, running SyncReleasesWithTags" , oldnum )
2020-01-21 04:01:19 +08:00
if err = repo_module . SyncReleasesWithTags ( repo , gitRepo ) ; err != nil {
2017-12-31 22:45:46 +08:00
log . Warn ( " SyncReleasesWithTags: %v" , err )
2019-11-13 15:01:19 +08:00
gitRepo . Close ( )
2017-12-31 22:45:46 +08:00
continue
}
2018-01-13 06:16:49 +08:00
count , err = getReleaseCount ( repo . ID )
2017-12-31 22:45:46 +08:00
if err != nil {
log . Warn ( " GetReleaseCountByRepoID: %v" , err )
2019-11-13 15:01:19 +08:00
gitRepo . Close ( )
2017-12-31 22:45:46 +08:00
continue
}
log . Trace ( " repo %s releases synchronized to tags: from %d to %d" ,
repo . FullName ( ) , oldnum , count )
2019-11-13 15:01:19 +08:00
gitRepo . Close ( )
2017-12-31 22:45:46 +08:00
}
}
return nil
}
2018-01-13 06:16:49 +08:00
func getReleaseCount ( id int64 ) ( int64 , error ) {
2022-08-25 10:31:57 +08:00
return repo_model . GetReleaseCountByRepoID (
2022-12-10 10:46:31 +08:00
db . DefaultContext ,
2018-01-13 06:16:49 +08:00
id ,
2022-08-25 10:31:57 +08:00
repo_model . FindReleasesOptions {
2018-01-13 06:16:49 +08:00
IncludeTags : true ,
} ,
)
}
2018-05-17 09:35:07 +08:00
2021-04-09 15:40:34 +08:00
func runRegenerateHooks ( _ * cli . Context ) error {
2021-11-07 11:11:27 +08:00
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
2018-05-17 09:35:07 +08:00
return err
}
2021-11-17 23:17:31 +08:00
return repo_service . SyncRepositoryHooks ( graceful . GetManager ( ) . ShutdownContext ( ) )
2018-05-17 09:35:07 +08:00
}
2021-04-09 15:40:34 +08:00
func runRegenerateKeys ( _ * cli . Context ) error {
2021-11-07 11:11:27 +08:00
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
2018-05-17 09:35:07 +08:00
return err
}
2021-12-10 16:14:24 +08:00
return asymkey_model . RewriteAllPublicKeys ( )
2018-05-17 09:35:07 +08:00
}
2018-09-12 22:46:02 +08:00
2021-07-24 18:16:34 +08:00
func parseOAuth2Config ( c * cli . Context ) * oauth2 . Source {
2018-09-12 22:46:02 +08:00
var customURLMapping * oauth2 . CustomURLMapping
if c . IsSet ( "use-custom-urls" ) {
customURLMapping = & oauth2 . CustomURLMapping {
TokenURL : c . String ( "custom-token-url" ) ,
AuthURL : c . String ( "custom-auth-url" ) ,
ProfileURL : c . String ( "custom-profile-url" ) ,
EmailURL : c . String ( "custom-email-url" ) ,
2023-02-06 12:12:13 +08:00
Tenant : c . String ( "custom-tenant-id" ) ,
2018-09-12 22:46:02 +08:00
}
} else {
customURLMapping = nil
}
2021-07-24 18:16:34 +08:00
return & oauth2 . Source {
2018-09-12 22:46:02 +08:00
Provider : c . String ( "provider" ) ,
ClientID : c . String ( "key" ) ,
ClientSecret : c . String ( "secret" ) ,
OpenIDConnectAutoDiscoveryURL : c . String ( "auto-discover-url" ) ,
CustomURLMapping : customURLMapping ,
2020-12-28 16:39:12 +08:00
IconURL : c . String ( "icon-url" ) ,
2021-09-11 00:37:57 +08:00
SkipLocalTwoFA : c . Bool ( "skip-local-2fa" ) ,
2021-12-14 16:37:11 +08:00
Scopes : c . StringSlice ( "scopes" ) ,
RequiredClaimName : c . String ( "required-claim-name" ) ,
RequiredClaimValue : c . String ( "required-claim-value" ) ,
GroupClaimName : c . String ( "group-claim-name" ) ,
AdminGroup : c . String ( "admin-group" ) ,
RestrictedGroup : c . String ( "restricted-group" ) ,
2023-02-08 14:44:42 +08:00
GroupTeamMap : c . String ( "group-team-map" ) ,
GroupTeamMapRemoval : c . Bool ( "group-team-map-removal" ) ,
2018-09-12 22:46:02 +08:00
}
}
func runAddOauth ( c * cli . Context ) error {
2021-11-07 11:11:27 +08:00
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
2018-09-12 22:46:02 +08:00
return err
}
2022-08-25 10:31:57 +08:00
return auth_model . CreateSource ( & auth_model . Source {
Type : auth_model . OAuth2 ,
2021-07-24 18:16:34 +08:00
Name : c . String ( "name" ) ,
IsActive : true ,
Cfg : parseOAuth2Config ( c ) ,
2018-10-18 12:51:07 +08:00
} )
2018-09-12 22:46:02 +08:00
}
func runUpdateOauth ( c * cli . Context ) error {
if ! c . IsSet ( "id" ) {
return fmt . Errorf ( "--id flag is missing" )
}
2021-11-07 11:11:27 +08:00
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
2018-09-12 22:46:02 +08:00
return err
}
2022-08-25 10:31:57 +08:00
source , err := auth_model . GetSourceByID ( c . Int64 ( "id" ) )
2018-09-12 22:46:02 +08:00
if err != nil {
return err
}
2021-07-24 18:16:34 +08:00
oAuth2Config := source . Cfg . ( * oauth2 . Source )
2018-09-12 22:46:02 +08:00
if c . IsSet ( "name" ) {
source . Name = c . String ( "name" )
}
if c . IsSet ( "provider" ) {
oAuth2Config . Provider = c . String ( "provider" )
}
if c . IsSet ( "key" ) {
oAuth2Config . ClientID = c . String ( "key" )
}
if c . IsSet ( "secret" ) {
oAuth2Config . ClientSecret = c . String ( "secret" )
}
if c . IsSet ( "auto-discover-url" ) {
oAuth2Config . OpenIDConnectAutoDiscoveryURL = c . String ( "auto-discover-url" )
}
2020-12-28 16:39:12 +08:00
if c . IsSet ( "icon-url" ) {
oAuth2Config . IconURL = c . String ( "icon-url" )
}
2021-12-14 16:37:11 +08:00
if c . IsSet ( "scopes" ) {
oAuth2Config . Scopes = c . StringSlice ( "scopes" )
}
if c . IsSet ( "required-claim-name" ) {
oAuth2Config . RequiredClaimName = c . String ( "required-claim-name" )
}
if c . IsSet ( "required-claim-value" ) {
oAuth2Config . RequiredClaimValue = c . String ( "required-claim-value" )
}
if c . IsSet ( "group-claim-name" ) {
oAuth2Config . GroupClaimName = c . String ( "group-claim-name" )
}
if c . IsSet ( "admin-group" ) {
oAuth2Config . AdminGroup = c . String ( "admin-group" )
}
if c . IsSet ( "restricted-group" ) {
oAuth2Config . RestrictedGroup = c . String ( "restricted-group" )
}
2023-02-08 14:44:42 +08:00
if c . IsSet ( "group-team-map" ) {
oAuth2Config . GroupTeamMap = c . String ( "group-team-map" )
}
if c . IsSet ( "group-team-map-removal" ) {
oAuth2Config . GroupTeamMapRemoval = c . Bool ( "group-team-map-removal" )
}
2021-12-14 16:37:11 +08:00
2018-09-12 22:46:02 +08:00
// update custom URL mapping
2022-01-21 01:46:10 +08:00
customURLMapping := & oauth2 . CustomURLMapping { }
2018-09-12 22:46:02 +08:00
if oAuth2Config . CustomURLMapping != nil {
customURLMapping . TokenURL = oAuth2Config . CustomURLMapping . TokenURL
customURLMapping . AuthURL = oAuth2Config . CustomURLMapping . AuthURL
customURLMapping . ProfileURL = oAuth2Config . CustomURLMapping . ProfileURL
customURLMapping . EmailURL = oAuth2Config . CustomURLMapping . EmailURL
2023-02-06 12:12:13 +08:00
customURLMapping . Tenant = oAuth2Config . CustomURLMapping . Tenant
2018-09-12 22:46:02 +08:00
}
if c . IsSet ( "use-custom-urls" ) && c . IsSet ( "custom-token-url" ) {
customURLMapping . TokenURL = c . String ( "custom-token-url" )
}
if c . IsSet ( "use-custom-urls" ) && c . IsSet ( "custom-auth-url" ) {
customURLMapping . AuthURL = c . String ( "custom-auth-url" )
}
if c . IsSet ( "use-custom-urls" ) && c . IsSet ( "custom-profile-url" ) {
customURLMapping . ProfileURL = c . String ( "custom-profile-url" )
}
if c . IsSet ( "use-custom-urls" ) && c . IsSet ( "custom-email-url" ) {
customURLMapping . EmailURL = c . String ( "custom-email-url" )
}
2023-02-06 12:12:13 +08:00
if c . IsSet ( "use-custom-urls" ) && c . IsSet ( "custom-tenant-id" ) {
customURLMapping . Tenant = c . String ( "custom-tenant-id" )
}
2018-09-12 22:46:02 +08:00
oAuth2Config . CustomURLMapping = customURLMapping
source . Cfg = oAuth2Config
2022-08-25 10:31:57 +08:00
return auth_model . UpdateSource ( source )
2018-09-12 22:46:02 +08:00
}
2022-01-13 06:54:53 +08:00
func parseSMTPConfig ( c * cli . Context , conf * smtp . Source ) error {
if c . IsSet ( "auth-type" ) {
conf . Auth = c . String ( "auth-type" )
validAuthTypes := [ ] string { "PLAIN" , "LOGIN" , "CRAM-MD5" }
Improve utils of slices (#22379)
- Move the file `compare.go` and `slice.go` to `slice.go`.
- Fix `ExistsInSlice`, it's buggy
- It uses `sort.Search`, so it assumes that the input slice is sorted.
- It passes `func(i int) bool { return slice[i] == target })` to
`sort.Search`, that's incorrect, check the doc of `sort.Search`.
- Conbine `IsInt64InSlice(int64, []int64)` and `ExistsInSlice(string,
[]string)` to `SliceContains[T]([]T, T)`.
- Conbine `IsSliceInt64Eq([]int64, []int64)` and `IsEqualSlice([]string,
[]string)` to `SliceSortedEqual[T]([]T, T)`.
- Add `SliceEqual[T]([]T, T)` as a distinction from
`SliceSortedEqual[T]([]T, T)`.
- Redesign `RemoveIDFromList([]int64, int64) ([]int64, bool)` to
`SliceRemoveAll[T]([]T, T) []T`.
- Add `SliceContainsFunc[T]([]T, func(T) bool)` and
`SliceRemoveAllFunc[T]([]T, func(T) bool)` for general use.
- Add comments to explain why not `golang.org/x/exp/slices`.
- Add unit tests.
2023-01-11 13:31:16 +08:00
if ! util . SliceContainsString ( validAuthTypes , strings . ToUpper ( c . String ( "auth-type" ) ) ) {
2022-01-13 06:54:53 +08:00
return errors . New ( "Auth must be one of PLAIN/LOGIN/CRAM-MD5" )
}
conf . Auth = c . String ( "auth-type" )
}
2022-11-11 05:12:23 +08:00
if c . IsSet ( "host" ) {
conf . Host = c . String ( "host" )
2022-01-13 06:54:53 +08:00
}
if c . IsSet ( "port" ) {
conf . Port = c . Int ( "port" )
}
if c . IsSet ( "allowed-domains" ) {
conf . AllowedDomains = c . String ( "allowed-domains" )
}
if c . IsSet ( "force-smtps" ) {
conf . ForceSMTPS = c . BoolT ( "force-smtps" )
}
if c . IsSet ( "skip-verify" ) {
conf . SkipVerify = c . BoolT ( "skip-verify" )
}
if c . IsSet ( "helo-hostname" ) {
conf . HeloHostname = c . String ( "helo-hostname" )
}
if c . IsSet ( "disable-helo" ) {
conf . DisableHelo = c . BoolT ( "disable-helo" )
}
if c . IsSet ( "skip-local-2fa" ) {
conf . SkipLocalTwoFA = c . BoolT ( "skip-local-2fa" )
}
return nil
}
func runAddSMTP ( c * cli . Context ) error {
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
return err
}
if ! c . IsSet ( "name" ) || len ( c . String ( "name" ) ) == 0 {
return errors . New ( "name must be set" )
}
if ! c . IsSet ( "host" ) || len ( c . String ( "host" ) ) == 0 {
return errors . New ( "host must be set" )
}
if ! c . IsSet ( "port" ) {
return errors . New ( "port must be set" )
}
2022-01-21 01:46:10 +08:00
active := true
2022-01-13 06:54:53 +08:00
if c . IsSet ( "active" ) {
active = c . BoolT ( "active" )
}
var smtpConfig smtp . Source
if err := parseSMTPConfig ( c , & smtpConfig ) ; err != nil {
return err
}
// If not set default to PLAIN
if len ( smtpConfig . Auth ) == 0 {
smtpConfig . Auth = "PLAIN"
}
2022-08-25 10:31:57 +08:00
return auth_model . CreateSource ( & auth_model . Source {
Type : auth_model . SMTP ,
2022-01-13 06:54:53 +08:00
Name : c . String ( "name" ) ,
IsActive : active ,
Cfg : & smtpConfig ,
} )
}
func runUpdateSMTP ( c * cli . Context ) error {
if ! c . IsSet ( "id" ) {
return fmt . Errorf ( "--id flag is missing" )
}
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
return err
}
2022-08-25 10:31:57 +08:00
source , err := auth_model . GetSourceByID ( c . Int64 ( "id" ) )
2022-01-13 06:54:53 +08:00
if err != nil {
return err
}
smtpConfig := source . Cfg . ( * smtp . Source )
if err := parseSMTPConfig ( c , smtpConfig ) ; err != nil {
return err
}
if c . IsSet ( "name" ) {
source . Name = c . String ( "name" )
}
if c . IsSet ( "active" ) {
source . IsActive = c . BoolT ( "active" )
}
source . Cfg = smtpConfig
2022-08-25 10:31:57 +08:00
return auth_model . UpdateSource ( source )
2022-01-13 06:54:53 +08:00
}
2018-09-12 22:46:02 +08:00
func runListAuth ( c * cli . Context ) error {
2021-11-07 11:11:27 +08:00
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
2018-09-12 22:46:02 +08:00
return err
}
2022-08-25 10:31:57 +08:00
authSources , err := auth_model . Sources ( )
2018-09-12 22:46:02 +08:00
if err != nil {
return err
}
2020-03-28 05:26:43 +08:00
flags := tabwriter . AlignRight
if c . Bool ( "vertical-bars" ) {
flags |= tabwriter . Debug
}
padChar := byte ( '\t' )
if len ( c . String ( "pad-char" ) ) > 0 {
padChar = c . String ( "pad-char" ) [ 0 ]
}
2018-09-12 22:46:02 +08:00
// loop through each source and print
2020-03-28 05:26:43 +08:00
w := tabwriter . NewWriter ( os . Stdout , c . Int ( "min-width" ) , c . Int ( "tab-width" ) , c . Int ( "padding" ) , padChar , flags )
2020-01-08 07:41:16 +08:00
fmt . Fprintf ( w , "ID\tName\tType\tEnabled\n" )
2022-01-02 21:12:35 +08:00
for _ , source := range authSources {
2021-09-24 19:32:56 +08:00
fmt . Fprintf ( w , "%d\t%s\t%s\t%t\n" , source . ID , source . Name , source . Type . String ( ) , source . IsActive )
2018-09-12 22:46:02 +08:00
}
w . Flush ( )
return nil
}
func runDeleteAuth ( c * cli . Context ) error {
if ! c . IsSet ( "id" ) {
return fmt . Errorf ( "--id flag is missing" )
}
2021-11-07 11:11:27 +08:00
ctx , cancel := installSignals ( )
defer cancel ( )
if err := initDB ( ctx ) ; err != nil {
2018-09-12 22:46:02 +08:00
return err
}
2022-08-25 10:31:57 +08:00
source , err := auth_model . GetSourceByID ( c . Int64 ( "id" ) )
2018-09-12 22:46:02 +08:00
if err != nil {
return err
}
2022-01-02 21:12:35 +08:00
return auth_service . DeleteSource ( source )
2018-09-12 22:46:02 +08:00
}