Improving command line interface (#4689)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
dcf11a14d8
Коммит
026553e4f8
284
cmd/platform/channel.go
Обычный файл
284
cmd/platform/channel.go
Обычный файл
@@ -0,0 +1,284 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/model"
|
||||
"github.com/mattermost/platform/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var channelCmd = &cobra.Command{
|
||||
Use: "channel",
|
||||
Short: "Management of channels",
|
||||
}
|
||||
|
||||
var channelCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a channel",
|
||||
Long: `Create a channel.`,
|
||||
Example: ` channel create --team myteam --name mynewchannel --display_name "My New Channel"
|
||||
channel create --team myteam --name mynewprivatechannel --display_name "My New Private Channel" --private`,
|
||||
RunE: createChannelCmdF,
|
||||
}
|
||||
|
||||
var removeChannelUsersCmd = &cobra.Command{
|
||||
Use: "remove [channel] [users]",
|
||||
Short: "Remove users from channel",
|
||||
Long: "Remove some users from channel",
|
||||
Example: " channel remove mychannel user@example.com username",
|
||||
RunE: removeChannelUsersCmdF,
|
||||
}
|
||||
|
||||
var addChannelUsersCmd = &cobra.Command{
|
||||
Use: "add [channel] [users]",
|
||||
Short: "Add users to channel",
|
||||
Long: "Add some users to channel",
|
||||
Example: " channel add mychannel user@example.com username",
|
||||
RunE: addChannelUsersCmdF,
|
||||
}
|
||||
|
||||
var deleteChannelsCmd = &cobra.Command{
|
||||
Use: "delete [channels]",
|
||||
Short: "Delete channels",
|
||||
Long: `Permanently delete some channels.
|
||||
Permanently deletes a channel along with all related information including posts from the database.
|
||||
Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
|
||||
Example: " channel delete myteam:mychannel",
|
||||
RunE: deleteChannelsCmdF,
|
||||
}
|
||||
|
||||
var listChannelsCmd = &cobra.Command{
|
||||
Use: "list [teams]",
|
||||
Short: "List all channels on specified teams.",
|
||||
Long: `List all channels on specified teams.
|
||||
Archived channels are appended with ' (archived)'.`,
|
||||
Example: " channel list myteam",
|
||||
RunE: listChannelsCmdF,
|
||||
}
|
||||
|
||||
var restoreChannelsCmd = &cobra.Command{
|
||||
Use: "restore [channels]",
|
||||
Short: "Restore some channels",
|
||||
Long: `Restore a previously deleted channel
|
||||
Channels can be specified by [team]:[channel]. ie. myteam:mychannel or by channel ID.`,
|
||||
Example: " channel restore myteam:mychannel",
|
||||
RunE: restoreChannelsCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
channelCreateCmd.Flags().String("name", "", "Channel Name")
|
||||
channelCreateCmd.Flags().String("display_name", "", "Channel Display Name")
|
||||
channelCreateCmd.Flags().String("team", "", "Team name or ID")
|
||||
channelCreateCmd.Flags().String("header", "", "Channel header")
|
||||
channelCreateCmd.Flags().String("purpose", "", "Channel purpose")
|
||||
channelCreateCmd.Flags().Bool("private", false, "Create a private channel.")
|
||||
|
||||
channelCmd.AddCommand(
|
||||
channelCreateCmd,
|
||||
removeChannelUsersCmd,
|
||||
addChannelUsersCmd,
|
||||
deleteChannelsCmd,
|
||||
listChannelsCmd,
|
||||
restoreChannelsCmd,
|
||||
)
|
||||
}
|
||||
|
||||
func createChannelCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if !utils.IsLicensed {
|
||||
return errors.New(utils.T("cli.license.critical"))
|
||||
}
|
||||
|
||||
name, errn := cmd.Flags().GetString("name")
|
||||
if errn != nil || name == "" {
|
||||
return errors.New("Name is required")
|
||||
}
|
||||
displayname, errdn := cmd.Flags().GetString("display_name")
|
||||
if errdn != nil || displayname == "" {
|
||||
return errors.New("Display Name is required")
|
||||
}
|
||||
teamArg, errteam := cmd.Flags().GetString("team")
|
||||
if errteam != nil || teamArg == "" {
|
||||
return errors.New("Team is required")
|
||||
}
|
||||
header, _ := cmd.Flags().GetString("header")
|
||||
purpose, _ := cmd.Flags().GetString("purpose")
|
||||
useprivate, _ := cmd.Flags().GetBool("private")
|
||||
|
||||
channelType := model.CHANNEL_OPEN
|
||||
if useprivate {
|
||||
channelType = model.CHANNEL_PRIVATE
|
||||
}
|
||||
|
||||
team := getTeamFromTeamArg(teamArg)
|
||||
|
||||
channel := &model.Channel{
|
||||
TeamId: team.Id,
|
||||
Name: name,
|
||||
DisplayName: displayname,
|
||||
Header: header,
|
||||
Purpose: purpose,
|
||||
Type: channelType,
|
||||
}
|
||||
|
||||
c := getMockContext()
|
||||
if _, err := api.CreateChannel(c, channel, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeChannelUsersCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if !utils.IsLicensed {
|
||||
return errors.New(utils.T("cli.license.critical"))
|
||||
}
|
||||
|
||||
if len(args) < 2 {
|
||||
return errors.New("Not enough arguments.")
|
||||
}
|
||||
|
||||
channel := getChannelFromChannelArg(args[0])
|
||||
if channel == nil {
|
||||
return errors.New("Unable to find channel '" + args[0] + "'")
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args[1:])
|
||||
for i, user := range users {
|
||||
removeUserFromChannel(channel, user, args[i+1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeUserFromChannel(channel *model.Channel, user *model.User, userArg string) {
|
||||
if user == nil {
|
||||
CommandPrintErrorln("Can't find user '" + userArg + "'")
|
||||
return
|
||||
}
|
||||
if err := api.RemoveUserFromChannel(user.Id, "", channel); err != nil {
|
||||
CommandPrintErrorln("Unable to remove '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func addChannelUsersCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if !utils.IsLicensed {
|
||||
return errors.New(utils.T("cli.license.critical"))
|
||||
}
|
||||
|
||||
if len(args) < 2 {
|
||||
return errors.New("Not enough arguments.")
|
||||
}
|
||||
|
||||
channel := getChannelFromChannelArg(args[0])
|
||||
if channel == nil {
|
||||
return errors.New("Unable to find channel '" + args[0] + "'")
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args[1:])
|
||||
for i, user := range users {
|
||||
addUserToChannel(channel, user, args[i+1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addUserToChannel(channel *model.Channel, user *model.User, userArg string) {
|
||||
if user == nil {
|
||||
CommandPrintErrorln("Can't find user '" + userArg + "'")
|
||||
return
|
||||
}
|
||||
if _, err := api.AddUserToChannel(user, channel); err != nil {
|
||||
CommandPrintErrorln("Unable to add '" + userArg + "' from " + channel.Name + ". Error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func deleteChannelsCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter at least one channel to delete.")
|
||||
}
|
||||
|
||||
channels := getChannelsFromChannelArgs(args)
|
||||
for i, channel := range channels {
|
||||
if channel == nil {
|
||||
CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
|
||||
continue
|
||||
}
|
||||
if result := <-api.Srv.Store.Channel().Delete(channel.Id, model.GetMillis()); result.Err != nil {
|
||||
CommandPrintErrorln("Unable to delete channel '" + channel.Name + "' error: " + result.Err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func listChannelsCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if !utils.IsLicensed {
|
||||
return errors.New(utils.T("cli.license.critical"))
|
||||
}
|
||||
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter at least one team.")
|
||||
}
|
||||
|
||||
teams := getTeamsFromTeamArgs(args)
|
||||
for i, team := range teams {
|
||||
if team == nil {
|
||||
CommandPrintErrorln("Unable to find team '" + args[i] + "'")
|
||||
continue
|
||||
}
|
||||
if result := <-api.Srv.Store.Channel().GetAll(team.Id); result.Err != nil {
|
||||
CommandPrintErrorln("Unable to list channels for '" + args[i] + "'")
|
||||
} else {
|
||||
channels := result.Data.([]*model.Channel)
|
||||
|
||||
for _, channel := range channels {
|
||||
if channel.DeleteAt > 0 {
|
||||
CommandPrettyPrintln(channel.Name + " (archived)")
|
||||
} else {
|
||||
CommandPrettyPrintln(channel.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func restoreChannelsCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if !utils.IsLicensed {
|
||||
return errors.New(utils.T("cli.license.critical"))
|
||||
}
|
||||
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter at least one channel.")
|
||||
}
|
||||
|
||||
channels := getChannelsFromChannelArgs(args)
|
||||
for i, channel := range channels {
|
||||
if channel == nil {
|
||||
CommandPrintErrorln("Unable to find channel '" + args[i] + "'")
|
||||
continue
|
||||
}
|
||||
if result := <-api.Srv.Store.Channel().SetDeleteAt(channel.Id, 0, model.GetMillis()); result.Err != nil {
|
||||
CommandPrintErrorln("Unable to restore channel '" + args[i] + "'")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
59
cmd/platform/channelargs.go
Обычный файл
59
cmd/platform/channelargs.go
Обычный файл
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/model"
|
||||
)
|
||||
|
||||
const CHANNEL_ARG_SEPARATOR = ":"
|
||||
|
||||
func getChannelsFromChannelArgs(channelArgs []string) []*model.Channel {
|
||||
channels := make([]*model.Channel, 0, len(channelArgs))
|
||||
for _, channelArg := range channelArgs {
|
||||
channel := getChannelFromChannelArg(channelArg)
|
||||
channels = append(channels, channel)
|
||||
}
|
||||
return channels
|
||||
}
|
||||
|
||||
func parseChannelArg(channelArg string) (string, string) {
|
||||
result := strings.SplitN(channelArg, CHANNEL_ARG_SEPARATOR, 2)
|
||||
if len(result) == 1 {
|
||||
return "", channelArg
|
||||
}
|
||||
return result[0], result[1]
|
||||
}
|
||||
|
||||
func getChannelFromChannelArg(channelArg string) *model.Channel {
|
||||
teamArg, channelPart := parseChannelArg(channelArg)
|
||||
if teamArg == "" && channelPart == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var channel *model.Channel
|
||||
if teamArg != "" {
|
||||
team := getTeamFromTeamArg(teamArg)
|
||||
if team == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if result := <-api.Srv.Store.Channel().GetByNameIncludeDeleted(team.Id, channelPart); result.Err == nil {
|
||||
channel = result.Data.(*model.Channel)
|
||||
} else {
|
||||
fmt.Println(result.Err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if channel == nil {
|
||||
if result := <-api.Srv.Store.Channel().Get(channelPart); result.Err == nil {
|
||||
channel = result.Data.(*model.Channel)
|
||||
}
|
||||
}
|
||||
|
||||
return channel
|
||||
}
|
||||
62
cmd/platform/import.go
Обычный файл
62
cmd/platform/import.go
Обычный файл
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var importCmd = &cobra.Command{
|
||||
Use: "import",
|
||||
Short: "Import data.",
|
||||
}
|
||||
|
||||
var slackImportCmd = &cobra.Command{
|
||||
Use: "slack [team] [file]",
|
||||
Short: "Import a team from Slack.",
|
||||
Long: "Import a team from a Slack export zip file.",
|
||||
Example: " import slack myteam slack_export.zip",
|
||||
RunE: slackImportCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
importCmd.AddCommand(
|
||||
slackImportCmd,
|
||||
)
|
||||
}
|
||||
|
||||
func slackImportCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if len(args) != 2 {
|
||||
return errors.New("Incorrect number of arguments.")
|
||||
}
|
||||
|
||||
team := getTeamFromTeamArg(args[0])
|
||||
if team == nil {
|
||||
return errors.New("Unable to find team '" + args[0] + "'")
|
||||
}
|
||||
|
||||
fileReader, err := os.Open(args[1])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fileReader.Close()
|
||||
|
||||
fileInfo, err := fileReader.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
CommandPrettyPrintln("Running Slack Import. This may take a long time for large teams or teams with many messages.")
|
||||
|
||||
api.SlackImport(fileReader, fileInfo.Size(), team.Id)
|
||||
|
||||
CommandPrettyPrintln("Finished Slack Import.")
|
||||
|
||||
return nil
|
||||
}
|
||||
41
cmd/platform/init.go
Обычный файл
41
cmd/platform/init.go
Обычный файл
@@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func doLoadConfig(filename string) (err string) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = fmt.Sprintf("%v", r)
|
||||
}
|
||||
}()
|
||||
utils.TranslationsPreInit()
|
||||
utils.LoadConfig(filename)
|
||||
return ""
|
||||
}
|
||||
|
||||
func initDBCommandContextCobra(cmd *cobra.Command) error {
|
||||
config, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
initDBCommandContext(config)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initDBCommandContext(configFileLocation string) {
|
||||
if errstr := doLoadConfig(configFileLocation); errstr != "" {
|
||||
return
|
||||
}
|
||||
|
||||
utils.ConfigureCmdLineLog()
|
||||
|
||||
api.NewServer()
|
||||
api.InitStores()
|
||||
}
|
||||
39
cmd/platform/ldap.go
Обычный файл
39
cmd/platform/ldap.go
Обычный файл
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/platform/einterfaces"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var ldapCmd = &cobra.Command{
|
||||
Use: "ldap",
|
||||
Short: "LDAP related utilities",
|
||||
}
|
||||
|
||||
var ldapSyncCmd = &cobra.Command{
|
||||
Use: "sync",
|
||||
Short: "Synchronize now",
|
||||
Long: "Synchronize all LDAP users now.",
|
||||
Example: " ldap sync",
|
||||
RunE: ldapSyncCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
ldapCmd.AddCommand(
|
||||
ldapSyncCmd,
|
||||
)
|
||||
}
|
||||
|
||||
func ldapSyncCmdF(cmd *cobra.Command, args []string) error {
|
||||
if ldapI := einterfaces.GetLdapInterface(); ldapI != nil {
|
||||
if err := ldapI.Syncronize(); err != nil {
|
||||
CommandPrintErrorln("ERROR: AD/LDAP Synchronization Failed")
|
||||
} else {
|
||||
CommandPrettyPrintln("SUCCESS: AD/LDAP Synchronization Complete")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
50
cmd/platform/license.go
Обычный файл
50
cmd/platform/license.go
Обычный файл
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var licenseCmd = &cobra.Command{
|
||||
Use: "license",
|
||||
Short: "Licensing commands",
|
||||
}
|
||||
|
||||
var uploadLicenseCmd = &cobra.Command{
|
||||
Use: "upload [license]",
|
||||
Short: "Upload a license.",
|
||||
Long: "Upload a license. Replaces current license.",
|
||||
Example: " license upload /path/to/license/mylicensefile.mattermost-license",
|
||||
RunE: uploadLicenseCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
licenseCmd.AddCommand(uploadLicenseCmd)
|
||||
}
|
||||
|
||||
func uploadLicenseCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if len(args) != 1 {
|
||||
return errors.New("Enter one license file to upload")
|
||||
}
|
||||
|
||||
var fileBytes []byte
|
||||
var err error
|
||||
if fileBytes, err = ioutil.ReadFile(args[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := api.SaveLicense(fileBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
CommandPrettyPrintln("Uploaded license file")
|
||||
|
||||
return nil
|
||||
}
|
||||
84
cmd/platform/mattermost.go
Обычный файл
84
cmd/platform/mattermost.go
Обычный файл
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
// Plugins
|
||||
_ "github.com/mattermost/platform/model/gitlab"
|
||||
|
||||
// Enterprise Deps
|
||||
_ "github.com/dgryski/dgoogauth"
|
||||
_ "github.com/go-ldap/ldap"
|
||||
_ "github.com/mattermost/rsc/qr"
|
||||
)
|
||||
|
||||
//ENTERPRISE_IMPORTS
|
||||
|
||||
func main() {
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "platform",
|
||||
Short: "Open source, self-hosted Slack-alternative",
|
||||
Long: `Mattermost offers workplace messaging across web, PC and phones with archiving, search and integration with your existing systems. Documentation available at https://docs.mattermost.com`,
|
||||
RunE: runServerCmd,
|
||||
}
|
||||
rootCmd.PersistentFlags().StringP("config", "c", "config.json", "Configuration file to use.")
|
||||
|
||||
resetCmd.Flags().Bool("confirm", false, "Confirm you really want to delete everything and a DB backup has been performed.")
|
||||
|
||||
rootCmd.AddCommand(serverCmd, versionCmd, userCmd, teamCmd, licenseCmd, importCmd, resetCmd, channelCmd, rolesCmd, testCmd, ldapCmd)
|
||||
|
||||
flag.Usage = func() {
|
||||
rootCmd.Usage()
|
||||
}
|
||||
parseCmds()
|
||||
|
||||
if flagRunCmds {
|
||||
CommandPrintErrorln("---------------------------------------------------------------------------------------------")
|
||||
CommandPrintErrorln("DEPRECATED! All previous commands are now deprecated. Run: platform help to see the new ones.")
|
||||
CommandPrintErrorln("---------------------------------------------------------------------------------------------")
|
||||
doLegacyCommands()
|
||||
} else {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var resetCmd = &cobra.Command{
|
||||
Use: "reset",
|
||||
Short: "Reset the database to initial state",
|
||||
Long: "Completely erases the database causing the loss of all data. This will reset Mattermost to its initial state.",
|
||||
RunE: resetCmdF,
|
||||
}
|
||||
|
||||
func resetCmdF(cmd *cobra.Command, args []string) error {
|
||||
confirmFlag, _ := cmd.Flags().GetBool("confirm")
|
||||
if !confirmFlag {
|
||||
var confirm string
|
||||
CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ")
|
||||
fmt.Scanln(&confirm)
|
||||
|
||||
if confirm != "YES" {
|
||||
return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
|
||||
}
|
||||
CommandPrettyPrintln("Are you sure you want to delete everything? All data will be permanently deleted? (YES/NO): ")
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "YES" {
|
||||
return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
|
||||
}
|
||||
}
|
||||
|
||||
api.Srv.Store.DropAllTables()
|
||||
CommandPrettyPrintln("Database sucessfully reset")
|
||||
|
||||
return nil
|
||||
}
|
||||
1102
cmd/platform/oldcommands.go
Обычный файл
1102
cmd/platform/oldcommands.go
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
32
cmd/platform/output.go
Обычный файл
32
cmd/platform/output.go
Обычный файл
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func CommandPrintln(a ...interface{}) (int, error) {
|
||||
return fmt.Println(a...)
|
||||
}
|
||||
|
||||
func CommandPrint(a ...interface{}) (int, error) {
|
||||
return fmt.Print(a...)
|
||||
}
|
||||
|
||||
func CommandPrintErrorln(a ...interface{}) (int, error) {
|
||||
return fmt.Fprintln(os.Stderr, a...)
|
||||
}
|
||||
|
||||
func CommandPrintError(a ...interface{}) (int, error) {
|
||||
return fmt.Fprint(os.Stderr, a...)
|
||||
}
|
||||
|
||||
func CommandPrettyPrintln(a ...interface{}) (int, error) {
|
||||
return fmt.Fprintln(os.Stderr, a...)
|
||||
}
|
||||
|
||||
func CommandPrettyPrint(a ...interface{}) (int, error) {
|
||||
return fmt.Fprint(os.Stderr, a...)
|
||||
}
|
||||
78
cmd/platform/roles.go
Обычный файл
78
cmd/platform/roles.go
Обычный файл
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var rolesCmd = &cobra.Command{
|
||||
Use: "roles",
|
||||
Short: "Management of user roles",
|
||||
}
|
||||
|
||||
var makeSystemAdminCmd = &cobra.Command{
|
||||
Use: "system_admin [users]",
|
||||
Short: "Set a user as system admin",
|
||||
Long: "Make some users system admins",
|
||||
Example: " roles system_admin user1",
|
||||
RunE: makeSystemAdminCmdF,
|
||||
}
|
||||
|
||||
var makeMemberCmd = &cobra.Command{
|
||||
Use: "member [users]",
|
||||
Short: "Remove system admin privileges",
|
||||
Long: "Remove system admin privileges from some users.",
|
||||
Example: " roles member user1",
|
||||
RunE: makeMemberCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
rolesCmd.AddCommand(
|
||||
makeSystemAdminCmd,
|
||||
makeMemberCmd,
|
||||
)
|
||||
}
|
||||
|
||||
func makeSystemAdminCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter at least one user.")
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args)
|
||||
for i, user := range users {
|
||||
if user == nil {
|
||||
return errors.New("Unable to find user '" + args[i] + "'")
|
||||
}
|
||||
|
||||
if _, err := api.UpdateUserRoles(user, "system_admin system_user"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeMemberCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter at least one user.")
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args)
|
||||
for i, user := range users {
|
||||
if user == nil {
|
||||
return errors.New("Unable to find user '" + args[i] + "'")
|
||||
}
|
||||
|
||||
if _, err := api.UpdateUserRoles(user, "system_user"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
277
cmd/platform/server.go
Обычный файл
277
cmd/platform/server.go
Обычный файл
@@ -0,0 +1,277 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
l4g "github.com/alecthomas/log4go"
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/einterfaces"
|
||||
"github.com/mattermost/platform/manualtesting"
|
||||
"github.com/mattermost/platform/model"
|
||||
"github.com/mattermost/platform/utils"
|
||||
"github.com/mattermost/platform/web"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var serverCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Run the Mattermost server",
|
||||
RunE: runServerCmd,
|
||||
}
|
||||
|
||||
func runServerCmd(cmd *cobra.Command, args []string) error {
|
||||
config, err := cmd.Flags().GetString("config")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
runServer(config)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runServer(configFileLocation string) {
|
||||
if errstr := doLoadConfig(configFileLocation); errstr != "" {
|
||||
l4g.Exit("Unable to load mattermost configuration file: ", errstr)
|
||||
return
|
||||
}
|
||||
|
||||
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
||||
utils.TestConnection(utils.Cfg)
|
||||
|
||||
pwd, _ := os.Getwd()
|
||||
l4g.Info(utils.T("mattermost.current_version"), model.CurrentVersion, model.BuildNumber, model.BuildDate, model.BuildHash, model.BuildHashEnterprise)
|
||||
l4g.Info(utils.T("mattermost.entreprise_enabled"), model.BuildEnterpriseReady)
|
||||
l4g.Info(utils.T("mattermost.working_dir"), pwd)
|
||||
l4g.Info(utils.T("mattermost.config_file"), utils.FindConfigFile(configFileLocation))
|
||||
|
||||
// Enable developer settings if this is a "dev" build
|
||||
if model.BuildNumber == "dev" {
|
||||
*utils.Cfg.ServiceSettings.EnableDeveloper = true
|
||||
}
|
||||
|
||||
cmdUpdateDb30()
|
||||
|
||||
api.NewServer()
|
||||
api.InitStores()
|
||||
api.InitRouter()
|
||||
api.InitApi()
|
||||
web.InitWeb()
|
||||
|
||||
if model.BuildEnterpriseReady == "true" {
|
||||
api.LoadLicense()
|
||||
}
|
||||
|
||||
if !utils.IsLicensed && len(utils.Cfg.SqlSettings.DataSourceReplicas) > 1 {
|
||||
l4g.Critical(utils.T("store.sql.read_replicas_not_licensed.critical"))
|
||||
return
|
||||
}
|
||||
|
||||
resetStatuses()
|
||||
|
||||
api.StartServer()
|
||||
|
||||
// If we allow testing then listen for manual testing URL hits
|
||||
if utils.Cfg.ServiceSettings.EnableTesting {
|
||||
manualtesting.InitManualTesting()
|
||||
}
|
||||
|
||||
setDiagnosticId()
|
||||
go runSecurityAndDiagnosticsJob()
|
||||
|
||||
if complianceI := einterfaces.GetComplianceInterface(); complianceI != nil {
|
||||
complianceI.StartComplianceDailyJob()
|
||||
}
|
||||
|
||||
if einterfaces.GetClusterInterface() != nil {
|
||||
einterfaces.GetClusterInterface().StartInterNodeCommunication()
|
||||
}
|
||||
|
||||
if einterfaces.GetMetricsInterface() != nil {
|
||||
einterfaces.GetMetricsInterface().StartServer()
|
||||
}
|
||||
|
||||
// wait for kill signal before attempting to gracefully shutdown
|
||||
// the running service
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-c
|
||||
|
||||
if einterfaces.GetClusterInterface() != nil {
|
||||
einterfaces.GetClusterInterface().StopInterNodeCommunication()
|
||||
}
|
||||
|
||||
if einterfaces.GetMetricsInterface() != nil {
|
||||
einterfaces.GetMetricsInterface().StopServer()
|
||||
}
|
||||
|
||||
api.StopServer()
|
||||
}
|
||||
|
||||
func runSecurityAndDiagnosticsJob() {
|
||||
doSecurityAndDiagnostics()
|
||||
model.CreateRecurringTask("Security and Diagnostics", doSecurityAndDiagnostics, time.Hour*4)
|
||||
}
|
||||
|
||||
func resetStatuses() {
|
||||
if result := <-api.Srv.Store.Status().ResetAll(); result.Err != nil {
|
||||
l4g.Error(utils.T("mattermost.reset_status.error"), result.Err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func setDiagnosticId() {
|
||||
if result := <-api.Srv.Store.System().Get(); result.Err == nil {
|
||||
props := result.Data.(model.StringMap)
|
||||
|
||||
id := props[model.SYSTEM_DIAGNOSTIC_ID]
|
||||
if len(id) == 0 {
|
||||
id = model.NewId()
|
||||
systemId := &model.System{Name: model.SYSTEM_DIAGNOSTIC_ID, Value: id}
|
||||
<-api.Srv.Store.System().Save(systemId)
|
||||
}
|
||||
|
||||
utils.CfgDiagnosticId = id
|
||||
}
|
||||
}
|
||||
|
||||
func doSecurityAndDiagnostics() {
|
||||
if *utils.Cfg.ServiceSettings.EnableSecurityFixAlert {
|
||||
if result := <-api.Srv.Store.System().Get(); result.Err == nil {
|
||||
props := result.Data.(model.StringMap)
|
||||
lastSecurityTime, _ := strconv.ParseInt(props[model.SYSTEM_LAST_SECURITY_TIME], 10, 0)
|
||||
currentTime := model.GetMillis()
|
||||
|
||||
if (currentTime - lastSecurityTime) > 1000*60*60*24*1 {
|
||||
l4g.Debug(utils.T("mattermost.security_checks.debug"))
|
||||
|
||||
v := url.Values{}
|
||||
|
||||
v.Set(utils.PROP_DIAGNOSTIC_ID, utils.CfgDiagnosticId)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_BUILD, model.CurrentVersion+"."+model.BuildNumber)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_ENTERPRISE_READY, model.BuildEnterpriseReady)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_DATABASE, utils.Cfg.SqlSettings.DriverName)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_OS, runtime.GOOS)
|
||||
v.Set(utils.PROP_DIAGNOSTIC_CATEGORY, utils.VAL_DIAGNOSTIC_CATEGORY_DEFAULT)
|
||||
|
||||
if len(props[model.SYSTEM_RAN_UNIT_TESTS]) > 0 {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_UNIT_TESTS, "1")
|
||||
} else {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_UNIT_TESTS, "0")
|
||||
}
|
||||
|
||||
systemSecurityLastTime := &model.System{Name: model.SYSTEM_LAST_SECURITY_TIME, Value: strconv.FormatInt(currentTime, 10)}
|
||||
if lastSecurityTime == 0 {
|
||||
<-api.Srv.Store.System().Save(systemSecurityLastTime)
|
||||
} else {
|
||||
<-api.Srv.Store.System().Update(systemSecurityLastTime)
|
||||
}
|
||||
|
||||
if ucr := <-api.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
|
||||
}
|
||||
|
||||
if ucr := <-api.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_ACTIVE_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
|
||||
}
|
||||
|
||||
if tcr := <-api.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
|
||||
v.Set(utils.PROP_DIAGNOSTIC_TEAM_COUNT, strconv.FormatInt(tcr.Data.(int64), 10))
|
||||
}
|
||||
|
||||
res, err := http.Get(utils.DIAGNOSTIC_URL + "/security?" + v.Encode())
|
||||
if err != nil {
|
||||
l4g.Error(utils.T("mattermost.security_info.error"))
|
||||
return
|
||||
}
|
||||
|
||||
bulletins := model.SecurityBulletinsFromJson(res.Body)
|
||||
ioutil.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
|
||||
for _, bulletin := range bulletins {
|
||||
if bulletin.AppliesToVersion == model.CurrentVersion {
|
||||
if props["SecurityBulletin_"+bulletin.Id] == "" {
|
||||
if results := <-api.Srv.Store.User().GetSystemAdminProfiles(); results.Err != nil {
|
||||
l4g.Error(utils.T("mattermost.system_admins.error"))
|
||||
return
|
||||
} else {
|
||||
users := results.Data.(map[string]*model.User)
|
||||
|
||||
resBody, err := http.Get(utils.DIAGNOSTIC_URL + "/bulletins/" + bulletin.Id)
|
||||
if err != nil {
|
||||
l4g.Error(utils.T("mattermost.security_bulletin.error"))
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resBody.Body)
|
||||
res.Body.Close()
|
||||
if err != nil || resBody.StatusCode != 200 {
|
||||
l4g.Error(utils.T("mattermost.security_bulletin_read.error"))
|
||||
return
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
l4g.Info(utils.T("mattermost.send_bulletin.info"), bulletin.Id, user.Email)
|
||||
utils.SendMail(user.Email, utils.T("mattermost.bulletin.subject"), string(body))
|
||||
}
|
||||
}
|
||||
|
||||
bulletinSeen := &model.System{Name: "SecurityBulletin_" + bulletin.Id, Value: bulletin.Id}
|
||||
<-api.Srv.Store.System().Save(bulletinSeen)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if *utils.Cfg.LogSettings.EnableDiagnostics {
|
||||
utils.SendGeneralDiagnostics()
|
||||
sendServerDiagnostics()
|
||||
}
|
||||
}
|
||||
|
||||
func sendServerDiagnostics() {
|
||||
var userCount int64
|
||||
var activeUserCount int64
|
||||
var teamCount int64
|
||||
|
||||
if ucr := <-api.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
|
||||
userCount = ucr.Data.(int64)
|
||||
}
|
||||
|
||||
if ucr := <-api.Srv.Store.Status().GetTotalActiveUsersCount(); ucr.Err == nil {
|
||||
activeUserCount = ucr.Data.(int64)
|
||||
}
|
||||
|
||||
if tcr := <-api.Srv.Store.Team().AnalyticsTeamCount(); tcr.Err == nil {
|
||||
teamCount = tcr.Data.(int64)
|
||||
}
|
||||
|
||||
utils.SendDiagnostic(utils.TRACK_ACTIVITY, map[string]interface{}{
|
||||
"registered_users": userCount,
|
||||
"active_users": activeUserCount,
|
||||
"teams": teamCount,
|
||||
})
|
||||
|
||||
edition := model.BuildEnterpriseReady
|
||||
version := model.CurrentVersion
|
||||
database := utils.Cfg.SqlSettings.DriverName
|
||||
operatingSystem := runtime.GOOS
|
||||
|
||||
utils.SendDiagnostic(utils.TRACK_VERSION, map[string]interface{}{
|
||||
"edition": edition,
|
||||
"version": version,
|
||||
"database": database,
|
||||
"operating_system": operatingSystem,
|
||||
})
|
||||
}
|
||||
205
cmd/platform/team.go
Обычный файл
205
cmd/platform/team.go
Обычный файл
@@ -0,0 +1,205 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/model"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var teamCmd = &cobra.Command{
|
||||
Use: "team",
|
||||
Short: "Management of teams",
|
||||
}
|
||||
|
||||
var teamCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a team",
|
||||
Long: `Create a team.`,
|
||||
Example: ` team create --name mynewteam --display_name "My New Team"
|
||||
teams create --name private --display_name "My New Private Team" --private`,
|
||||
RunE: createTeamCmdF,
|
||||
}
|
||||
|
||||
var removeUsersCmd = &cobra.Command{
|
||||
Use: "remove [team] [users]",
|
||||
Short: "Remove users from team",
|
||||
Long: "Remove some users from team",
|
||||
Example: " team remove myteam user@example.com username",
|
||||
RunE: removeUsersCmdF,
|
||||
}
|
||||
|
||||
var addUsersCmd = &cobra.Command{
|
||||
Use: "add [team] [users]",
|
||||
Short: "Add users to team",
|
||||
Long: "Add some users to team",
|
||||
Example: " team add myteam user@example.com username",
|
||||
RunE: addUsersCmdF,
|
||||
}
|
||||
|
||||
var deleteTeamsCmd = &cobra.Command{
|
||||
Use: "delete [teams]",
|
||||
Short: "Delete teams",
|
||||
Long: `Permanently delete some teams.
|
||||
Permanently deletes a team along with all related information including posts from the database.`,
|
||||
Example: " team delete myteam",
|
||||
RunE: deleteTeamsCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
teamCreateCmd.Flags().String("name", "", "Team Name")
|
||||
teamCreateCmd.Flags().String("display_name", "", "Team Display Name")
|
||||
teamCreateCmd.Flags().Bool("private", false, "Create a private team.")
|
||||
teamCreateCmd.Flags().String("email", "", "Administrator Email (anyone with this email is automatically a team admin)")
|
||||
|
||||
deleteTeamsCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the team and a DB backup has been performed.")
|
||||
|
||||
teamCmd.AddCommand(
|
||||
teamCreateCmd,
|
||||
removeUsersCmd,
|
||||
addUsersCmd,
|
||||
deleteTeamsCmd,
|
||||
)
|
||||
}
|
||||
|
||||
func createTeamCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
name, errn := cmd.Flags().GetString("name")
|
||||
if errn != nil || name == "" {
|
||||
return errors.New("Name is required")
|
||||
}
|
||||
displayname, errdn := cmd.Flags().GetString("display_name")
|
||||
if errdn != nil || displayname == "" {
|
||||
return errors.New("Display Name is required")
|
||||
}
|
||||
email, _ := cmd.Flags().GetString("email")
|
||||
useprivate, _ := cmd.Flags().GetBool("private")
|
||||
|
||||
teamType := model.TEAM_OPEN
|
||||
if useprivate {
|
||||
teamType = model.TEAM_INVITE
|
||||
}
|
||||
|
||||
team := &model.Team{
|
||||
Name: name,
|
||||
DisplayName: displayname,
|
||||
Email: email,
|
||||
Type: teamType,
|
||||
}
|
||||
|
||||
c := getMockContext()
|
||||
api.CreateTeam(c, team)
|
||||
if c.Err != nil {
|
||||
return errors.New("Team creation failed: " + c.Err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeUsersCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if len(args) < 2 {
|
||||
return errors.New("Not enough arguments.")
|
||||
}
|
||||
|
||||
team := getTeamFromTeamArg(args[0])
|
||||
if team == nil {
|
||||
return errors.New("Unable to find team '" + args[0] + "'")
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args[1:])
|
||||
for i, user := range users {
|
||||
removeUserFromTeam(team, user, args[i+1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func removeUserFromTeam(team *model.Team, user *model.User, userArg string) {
|
||||
if user == nil {
|
||||
CommandPrintErrorln("Can't find user '" + userArg + "'")
|
||||
return
|
||||
}
|
||||
if err := api.LeaveTeam(team, user); err != nil {
|
||||
CommandPrintErrorln("Unable to remove '" + userArg + "' from " + team.Name + ". Error: " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func addUsersCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if len(args) < 2 {
|
||||
return errors.New("Not enough arguments.")
|
||||
}
|
||||
|
||||
team := getTeamFromTeamArg(args[0])
|
||||
if team == nil {
|
||||
return errors.New("Unable to find team '" + args[0] + "'")
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args[1:])
|
||||
for i, user := range users {
|
||||
addUserToTeam(team, user, args[i+1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addUserToTeam(team *model.Team, user *model.User, userArg string) {
|
||||
if user == nil {
|
||||
CommandPrintErrorln("Can't find user '" + userArg + "'")
|
||||
return
|
||||
}
|
||||
if err := api.JoinUserToTeam(team, user); err != nil {
|
||||
CommandPrintErrorln("Unable to add '" + userArg + "' to " + team.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func deleteTeamsCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if len(args) < 1 {
|
||||
return errors.New("Not enough arguments.")
|
||||
}
|
||||
|
||||
confirmFlag, _ := cmd.Flags().GetBool("confirm")
|
||||
if !confirmFlag {
|
||||
var confirm string
|
||||
CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ")
|
||||
fmt.Scanln(&confirm)
|
||||
|
||||
if confirm != "YES" {
|
||||
return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
|
||||
}
|
||||
CommandPrettyPrintln("Are you sure you want to delete the teams specified? All data will be permanently deleted? (YES/NO): ")
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "YES" {
|
||||
return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
|
||||
}
|
||||
}
|
||||
|
||||
teams := getTeamsFromTeamArgs(args)
|
||||
for i, team := range teams {
|
||||
if team == nil {
|
||||
CommandPrintErrorln("Unable to find team '" + args[i] + "'")
|
||||
continue
|
||||
}
|
||||
if err := deleteTeam(team); err != nil {
|
||||
CommandPrintErrorln("Unable to delete team '" + team.Name + "' error: " + err.Error())
|
||||
} else {
|
||||
CommandPrettyPrintln("Deleted team '" + team.Name + "'")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteTeam(team *model.Team) *model.AppError {
|
||||
return api.PermanentDeleteTeam(team)
|
||||
}
|
||||
32
cmd/platform/teamargs.go
Обычный файл
32
cmd/platform/teamargs.go
Обычный файл
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/model"
|
||||
)
|
||||
|
||||
func getTeamsFromTeamArgs(teamArgs []string) []*model.Team {
|
||||
teams := make([]*model.Team, 0, len(teamArgs))
|
||||
for _, teamArg := range teamArgs {
|
||||
team := getTeamFromTeamArg(teamArg)
|
||||
teams = append(teams, team)
|
||||
}
|
||||
return teams
|
||||
}
|
||||
|
||||
func getTeamFromTeamArg(teamArg string) *model.Team {
|
||||
var team *model.Team
|
||||
if result := <-api.Srv.Store.Team().GetByName(teamArg); result.Err == nil {
|
||||
team = result.Data.(*model.Team)
|
||||
}
|
||||
|
||||
if team == nil {
|
||||
if result := <-api.Srv.Store.Team().Get(teamArg); result.Err == nil {
|
||||
team = result.Data.(*model.Team)
|
||||
}
|
||||
}
|
||||
|
||||
return team
|
||||
}
|
||||
82
cmd/platform/test.go
Обычный файл
82
cmd/platform/test.go
Обычный файл
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var testCmd = &cobra.Command{
|
||||
Use: "test",
|
||||
Short: "Testing Commands",
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
var runWebClientTestsCmd = &cobra.Command{
|
||||
Use: "web_client_tests",
|
||||
Short: "Run the web client tests",
|
||||
RunE: webClientTestsCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
testCmd.AddCommand(
|
||||
runWebClientTestsCmd,
|
||||
)
|
||||
}
|
||||
|
||||
func webClientTestsCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
utils.InitTranslations(utils.Cfg.LocalizationSettings)
|
||||
api.InitRouter()
|
||||
api.InitApi()
|
||||
setupClientTests()
|
||||
api.StartServer()
|
||||
runWebClientTests()
|
||||
api.StopServer()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setupClientTests() {
|
||||
*utils.Cfg.TeamSettings.EnableOpenServer = true
|
||||
*utils.Cfg.ServiceSettings.EnableCommands = false
|
||||
*utils.Cfg.ServiceSettings.EnableOnlyAdminIntegrations = false
|
||||
*utils.Cfg.ServiceSettings.EnableCustomEmoji = true
|
||||
utils.Cfg.ServiceSettings.EnableIncomingWebhooks = false
|
||||
utils.Cfg.ServiceSettings.EnableOutgoingWebhooks = false
|
||||
utils.SetDefaultRolesBasedOnConfig()
|
||||
}
|
||||
|
||||
func executeTestCommand(cmd *exec.Cmd) {
|
||||
cmdOutPipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
CommandPrintErrorln("Failed to run tests")
|
||||
return
|
||||
}
|
||||
|
||||
cmdOutReader := bufio.NewScanner(cmdOutPipe)
|
||||
go func() {
|
||||
for cmdOutReader.Scan() {
|
||||
fmt.Println(cmdOutReader.Text())
|
||||
}
|
||||
}()
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
CommandPrintErrorln("Client Tests failed")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func runWebClientTests() {
|
||||
os.Chdir("webapp")
|
||||
cmd := exec.Command("npm", "test")
|
||||
executeTestCommand(cmd)
|
||||
}
|
||||
432
cmd/platform/user.go
Обычный файл
432
cmd/platform/user.go
Обычный файл
@@ -0,0 +1,432 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/einterfaces"
|
||||
"github.com/mattermost/platform/model"
|
||||
"github.com/mattermost/platform/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var userCmd = &cobra.Command{
|
||||
Use: "user",
|
||||
Short: "Management of users",
|
||||
}
|
||||
|
||||
var userActivateCmd = &cobra.Command{
|
||||
Use: "activate [emails, usernames, userIds]",
|
||||
Short: "Activate users",
|
||||
Long: "Activate users that have been deactivated.",
|
||||
Example: ` user activate user@example.com
|
||||
user activate username`,
|
||||
RunE: userActivateCmdF,
|
||||
}
|
||||
|
||||
var userDeactivateCmd = &cobra.Command{
|
||||
Use: "deactivate [emails, usernames, userIds]",
|
||||
Short: "Deactivate users",
|
||||
Long: "Deactivate users. Deactivated users are immediately logged out of all sessions and are unable to log back in.",
|
||||
Example: ` user deactivate user@example.com
|
||||
user deactivate username`,
|
||||
RunE: userDeactivateCmdF,
|
||||
}
|
||||
|
||||
var userCreateCmd = &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a user",
|
||||
Long: "Create a user",
|
||||
Example: ` user create --email user@example.com --username userexample --password Password1
|
||||
user create --firstname Joe --system_admin --email joe@example.com --username joe --password Password1`,
|
||||
RunE: userCreateCmdF,
|
||||
}
|
||||
|
||||
var userInviteCmd = &cobra.Command{
|
||||
Use: "invite [email] [teams]",
|
||||
Short: "Send user an email invite to a team.",
|
||||
Long: `Send user an email invite to a team.
|
||||
You can invite a user to multiple teams by listing them.
|
||||
You can specify teams by name or ID.`,
|
||||
Example: ` user invite user@example.com myteam
|
||||
user invite user@example.com myteam1 myteam2`,
|
||||
RunE: userInviteCmdF,
|
||||
}
|
||||
|
||||
var resetUserPasswordCmd = &cobra.Command{
|
||||
Use: "password [user] [password]",
|
||||
Short: "Set a user's password",
|
||||
Long: "Set a user's password",
|
||||
Example: " user password user@example.com Password1",
|
||||
RunE: resetUserPasswordCmdF,
|
||||
}
|
||||
|
||||
var resetUserMfaCmd = &cobra.Command{
|
||||
Use: "resetmfa [users]",
|
||||
Short: "Turn off MFA",
|
||||
Long: `Turn off multi-factor authentication for a user.
|
||||
If MFA enforcement is enabled, the user will be forced to re-enable MFA as soon as they login.`,
|
||||
Example: " user resetmfa user@example.com",
|
||||
RunE: resetUserMfaCmdF,
|
||||
}
|
||||
|
||||
var deleteUserCmd = &cobra.Command{
|
||||
Use: "delete [users]",
|
||||
Short: "Delete users and all posts",
|
||||
Long: "Permanently delete user and all related information including posts.",
|
||||
Example: " user delete user@example.com",
|
||||
RunE: deleteUserCmdF,
|
||||
}
|
||||
|
||||
var deleteAllUsersCmd = &cobra.Command{
|
||||
Use: "deleteall",
|
||||
Short: "Delete all users and all posts",
|
||||
Long: "Permanently delete all users and all related information including posts.",
|
||||
Example: " user deleteall",
|
||||
RunE: deleteUserCmdF,
|
||||
}
|
||||
|
||||
var migrateAuthCmd = &cobra.Command{
|
||||
Use: "migrate_auth [from_auth] [to_auth] [match_field]",
|
||||
Short: "Mass migrate user accounts authentication type",
|
||||
Long: `Migrates accounts from one authentication provider to another. For example, you can upgrade your authentication provider from email to ldap.
|
||||
|
||||
from_auth:
|
||||
The authentication service to migrate users accounts from.
|
||||
Supported options: email, gitlab, saml.
|
||||
|
||||
to_auth:
|
||||
The authentication service to migrate users to.
|
||||
Supported options: ldap.
|
||||
|
||||
match_field:
|
||||
The field that is guaranteed to be the same in both authentication services. For example, if the users emails are consistent set to email.
|
||||
Supported options: email, username.
|
||||
|
||||
Will display any accounts that are not migrated successfully.`,
|
||||
Example: " user migrate_auth email ladp email",
|
||||
RunE: migrateAuthCmdF,
|
||||
}
|
||||
|
||||
var verifyUserCmd = &cobra.Command{
|
||||
Use: "verify [users]",
|
||||
Short: "Verify email of users",
|
||||
Long: "Verify the emails of some users.",
|
||||
Example: " user verify user1",
|
||||
RunE: verifyUserCmdF,
|
||||
}
|
||||
|
||||
func init() {
|
||||
userCreateCmd.Flags().String("username", "", "Username")
|
||||
userCreateCmd.Flags().String("email", "", "Email")
|
||||
userCreateCmd.Flags().String("password", "", "Password")
|
||||
userCreateCmd.Flags().String("nickname", "", "Nickname")
|
||||
userCreateCmd.Flags().String("firstname", "", "First Name")
|
||||
userCreateCmd.Flags().String("lastname", "", "Last Name")
|
||||
userCreateCmd.Flags().String("locale", "", "Locale (ex: en, fr)")
|
||||
userCreateCmd.Flags().Bool("system_admin", false, "Make the user a system administrator")
|
||||
|
||||
deleteUserCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the user and a DB backup has been performed.")
|
||||
|
||||
deleteAllUsersCmd.Flags().Bool("confirm", false, "Confirm you really want to delete the user and a DB backup has been performed.")
|
||||
|
||||
userCmd.AddCommand(
|
||||
userActivateCmd,
|
||||
userDeactivateCmd,
|
||||
userCreateCmd,
|
||||
userInviteCmd,
|
||||
resetUserPasswordCmd,
|
||||
resetUserMfaCmd,
|
||||
deleteUserCmd,
|
||||
deleteAllUsersCmd,
|
||||
migrateAuthCmd,
|
||||
verifyUserCmd,
|
||||
)
|
||||
}
|
||||
|
||||
func userActivateCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter user(s) to activate.")
|
||||
}
|
||||
|
||||
changeUsersActiveStatus(args, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func changeUsersActiveStatus(userArgs []string, active bool) {
|
||||
users := getUsersFromUserArgs(userArgs)
|
||||
for i, user := range users {
|
||||
changeUserActiveStatus(user, userArgs[i], active)
|
||||
}
|
||||
}
|
||||
|
||||
func changeUserActiveStatus(user *model.User, userArg string, activate bool) {
|
||||
if user == nil {
|
||||
CommandPrintErrorln("Can't find user '" + userArg + "'")
|
||||
return
|
||||
}
|
||||
if user.IsLDAPUser() {
|
||||
CommandPrintErrorln(utils.T("api.user.update_active.no_deactivate_ldap.app_error"))
|
||||
return
|
||||
}
|
||||
if _, err := api.UpdateActive(user, activate); err != nil {
|
||||
CommandPrintErrorln("Unable to change activation status of user: " + userArg)
|
||||
}
|
||||
}
|
||||
|
||||
func userDeactivateCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter user(s) to deactivate.")
|
||||
}
|
||||
|
||||
changeUsersActiveStatus(args, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
func userCreateCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
username, erru := cmd.Flags().GetString("username")
|
||||
if erru != nil || username == "" {
|
||||
return errors.New("Username is required")
|
||||
}
|
||||
email, erre := cmd.Flags().GetString("email")
|
||||
if erre != nil || email == "" {
|
||||
return errors.New("Email is required")
|
||||
}
|
||||
password, errp := cmd.Flags().GetString("password")
|
||||
if errp != nil || password == "" {
|
||||
return errors.New("Password is required")
|
||||
}
|
||||
nickname, _ := cmd.Flags().GetString("nickname")
|
||||
firstname, _ := cmd.Flags().GetString("firstname")
|
||||
lastname, _ := cmd.Flags().GetString("lastname")
|
||||
locale, _ := cmd.Flags().GetString("locale")
|
||||
system_admin, _ := cmd.Flags().GetBool("system_admin")
|
||||
|
||||
user := &model.User{
|
||||
Username: username,
|
||||
Email: email,
|
||||
Password: password,
|
||||
Nickname: nickname,
|
||||
FirstName: firstname,
|
||||
LastName: lastname,
|
||||
Locale: locale,
|
||||
}
|
||||
|
||||
ruser, err := api.CreateUser(user)
|
||||
if err != nil {
|
||||
return errors.New("Unable to create user. Error: " + err.Error())
|
||||
}
|
||||
|
||||
if system_admin {
|
||||
api.UpdateUserRoles(ruser, "system_user system_admin")
|
||||
}
|
||||
|
||||
CommandPrettyPrintln("Created User")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func userInviteCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
utils.InitHTML()
|
||||
|
||||
if len(args) < 2 {
|
||||
return errors.New("Not enough arguments.")
|
||||
}
|
||||
|
||||
email := args[0]
|
||||
if !model.IsValidEmail(email) {
|
||||
return errors.New("Invalid email")
|
||||
}
|
||||
|
||||
teams := getTeamsFromTeamArgs(args[1:])
|
||||
for i, team := range teams {
|
||||
inviteUser(email, team, args[i+1])
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func inviteUser(email string, team *model.Team, teamArg string) {
|
||||
invites := []string{email}
|
||||
if team == nil {
|
||||
CommandPrintErrorln("Can't find team '" + teamArg + "'")
|
||||
return
|
||||
}
|
||||
api.InviteMembers(team, "Administrator", invites)
|
||||
CommandPrettyPrintln("Invites may or may not have been sent.")
|
||||
}
|
||||
|
||||
func resetUserPasswordCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
if len(args) != 2 {
|
||||
return errors.New("Incorect number of arguments.")
|
||||
}
|
||||
|
||||
user := getUserFromUserArg(args[0])
|
||||
if user == nil {
|
||||
return errors.New("Unable to find user '" + args[0] + "'")
|
||||
}
|
||||
password := args[1]
|
||||
|
||||
if result := <-api.Srv.Store.User().UpdatePassword(user.Id, model.HashPassword(password)); result.Err != nil {
|
||||
return result.Err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resetUserMfaCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter at least one user.")
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args)
|
||||
|
||||
for i, user := range users {
|
||||
if user == nil {
|
||||
return errors.New("Unable to find user '" + args[i] + "'")
|
||||
}
|
||||
|
||||
if err := api.DeactivateMfa(user.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteUserCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter at least one user.")
|
||||
}
|
||||
|
||||
confirmFlag, _ := cmd.Flags().GetBool("confirm")
|
||||
if !confirmFlag {
|
||||
var confirm string
|
||||
CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ")
|
||||
fmt.Scanln(&confirm)
|
||||
|
||||
if confirm != "YES" {
|
||||
return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
|
||||
}
|
||||
CommandPrettyPrintln("Are you sure you want to delete the teams specified? All data will be permanently deleted? (YES/NO): ")
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "YES" {
|
||||
return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
|
||||
}
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args)
|
||||
|
||||
for i, user := range users {
|
||||
if user == nil {
|
||||
return errors.New("Unable to find user '" + args[i] + "'")
|
||||
}
|
||||
|
||||
if err := api.PermanentDeleteUser(user); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteAllUsersCommandF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
if len(args) > 0 {
|
||||
return errors.New("Don't enter any agruments.")
|
||||
}
|
||||
|
||||
confirmFlag, _ := cmd.Flags().GetBool("confirm")
|
||||
if !confirmFlag {
|
||||
var confirm string
|
||||
CommandPrettyPrintln("Have you performed a database backup? (YES/NO): ")
|
||||
fmt.Scanln(&confirm)
|
||||
|
||||
if confirm != "YES" {
|
||||
return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
|
||||
}
|
||||
CommandPrettyPrintln("Are you sure you want to delete the teams specified? All data will be permanently deleted? (YES/NO): ")
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "YES" {
|
||||
return errors.New("ABORTED: You did not answer YES exactly, in all capitals.")
|
||||
}
|
||||
}
|
||||
|
||||
if err := api.PermanentDeleteAllUsers(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
CommandPrettyPrintln("Sucsessfull. All users deleted.")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func migrateAuthCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
if len(args) != 3 {
|
||||
return errors.New("Enter the correct number of arguments.")
|
||||
}
|
||||
|
||||
fromAuth := args[0]
|
||||
toAuth := args[1]
|
||||
matchField := args[2]
|
||||
|
||||
if len(fromAuth) == 0 || (fromAuth != "email" && fromAuth != "gitlab" && fromAuth != "saml") {
|
||||
return errors.New("Invalid from_auth argument")
|
||||
}
|
||||
|
||||
if len(toAuth) == 0 || toAuth != "ldap" {
|
||||
return errors.New("Invalid to_auth argument")
|
||||
}
|
||||
|
||||
// Email auth in Mattermost system is represented by ""
|
||||
if fromAuth == "email" {
|
||||
fromAuth = ""
|
||||
}
|
||||
|
||||
if len(matchField) == 0 || (matchField != "email" && matchField != "username") {
|
||||
return errors.New("Invalid match_field argument")
|
||||
}
|
||||
|
||||
if migrate := einterfaces.GetAccountMigrationInterface(); migrate != nil {
|
||||
if err := migrate.MigrateToLdap(fromAuth, matchField); err != nil {
|
||||
return errors.New("Error while migrating users: " + err.Error())
|
||||
} else {
|
||||
CommandPrettyPrintln("Sucessfully migrated accounts.")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyUserCmdF(cmd *cobra.Command, args []string) error {
|
||||
initDBCommandContextCobra(cmd)
|
||||
if len(args) < 1 {
|
||||
return errors.New("Enter at least one user.")
|
||||
}
|
||||
|
||||
users := getUsersFromUserArgs(args)
|
||||
|
||||
for i, user := range users {
|
||||
if user == nil {
|
||||
CommandPrintErrorln("Unable to find user '" + args[i] + "'")
|
||||
}
|
||||
if cresult := <-api.Srv.Store.User().VerifyEmail(user.Id); cresult.Err != nil {
|
||||
CommandPrintErrorln("Unable to verify '" + args[i] + "' email. Error: " + cresult.Err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
38
cmd/platform/userargs.go
Обычный файл
38
cmd/platform/userargs.go
Обычный файл
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/model"
|
||||
)
|
||||
|
||||
func getUsersFromUserArgs(userArgs []string) []*model.User {
|
||||
users := make([]*model.User, 0, len(userArgs))
|
||||
for _, userArg := range userArgs {
|
||||
user := getUserFromUserArg(userArg)
|
||||
users = append(users, user)
|
||||
}
|
||||
return users
|
||||
}
|
||||
|
||||
func getUserFromUserArg(userArg string) *model.User {
|
||||
var user *model.User
|
||||
if result := <-api.Srv.Store.User().GetByEmail(userArg); result.Err == nil {
|
||||
user = result.Data.(*model.User)
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
if result := <-api.Srv.Store.User().GetByUsername(userArg); result.Err == nil {
|
||||
user = result.Data.(*model.User)
|
||||
}
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
if result := <-api.Srv.Store.User().Get(userArg); result.Err == nil {
|
||||
user = result.Data.(*model.User)
|
||||
}
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
30
cmd/platform/version.go
Обычный файл
30
cmd/platform/version.go
Обычный файл
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattermost/platform/api"
|
||||
"github.com/mattermost/platform/model"
|
||||
"github.com/mattermost/platform/store"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var versionCmd = &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Display version information",
|
||||
Run: versionCmdF,
|
||||
}
|
||||
|
||||
func versionCmdF(cmd *cobra.Command, args []string) {
|
||||
initDBCommandContextCobra(cmd)
|
||||
printVersion()
|
||||
}
|
||||
|
||||
func printVersion() {
|
||||
CommandPrintln("Version: " + model.CurrentVersion)
|
||||
CommandPrintln("Build Number: " + model.BuildNumber)
|
||||
CommandPrintln("Build Date: " + model.BuildDate)
|
||||
CommandPrintln("Build Hash: " + model.BuildHash)
|
||||
CommandPrintln("Build Enterprise Ready: " + model.BuildEnterpriseReady)
|
||||
CommandPrintln("DB Version: " + api.Srv.Store.(*store.SqlStore).SchemaVersion)
|
||||
}
|
||||
Ссылка в новой задаче
Block a user