mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
Adding team settings to admin console
This commit is contained in:
@@ -83,7 +83,7 @@ func TestGetConfig(t *testing.T) {
|
||||
} else {
|
||||
cfg := result.Data.(*model.Config)
|
||||
|
||||
if len(cfg.ServiceSettings.SiteName) == 0 {
|
||||
if len(cfg.TeamSettings.SiteName) == 0 {
|
||||
t.Fatal()
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ func TestSaveConfig(t *testing.T) {
|
||||
} else {
|
||||
cfg := result.Data.(*model.Config)
|
||||
|
||||
if len(cfg.ServiceSettings.SiteName) == 0 {
|
||||
if len(cfg.TeamSettings.SiteName) == 0 {
|
||||
t.Fatal()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ var Client *model.Client
|
||||
func Setup() {
|
||||
if Srv == nil {
|
||||
utils.LoadConfig("config.json")
|
||||
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
|
||||
NewServer()
|
||||
StartServer()
|
||||
InitApi()
|
||||
|
||||
@@ -471,7 +471,7 @@ func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request)
|
||||
m := make(map[string]string)
|
||||
m["Message"] = err.Message
|
||||
m["Details"] = err.DetailedError
|
||||
m["SiteName"] = utils.Cfg.ServiceSettings.SiteName
|
||||
m["SiteName"] = utils.Cfg.TeamSettings.SiteName
|
||||
m["SiteURL"] = SiteURL
|
||||
|
||||
w.WriteHeader(err.StatusCode)
|
||||
|
||||
@@ -447,7 +447,7 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if !utils.Cfg.TeamSettings.AllowPublicLink {
|
||||
if !utils.Cfg.ImageSettings.EnablePublicLink {
|
||||
c.Err = model.NewAppError("getPublicLink", "Public links have been disabled", "")
|
||||
c.Err.StatusCode = http.StatusForbidden
|
||||
}
|
||||
|
||||
70
api/post.go
70
api/post.go
@@ -25,7 +25,6 @@ func InitPost(r *mux.Router) {
|
||||
|
||||
sr := r.PathPrefix("/channels/{id:[A-Za-z0-9]+}").Subrouter()
|
||||
sr.Handle("/create", ApiUserRequired(createPost)).Methods("POST")
|
||||
sr.Handle("/valet_create", ApiUserRequired(createValetPost)).Methods("POST")
|
||||
sr.Handle("/update", ApiUserRequired(updatePost)).Methods("POST")
|
||||
sr.Handle("/posts/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequiredActivity(getPosts, false)).Methods("GET")
|
||||
sr.Handle("/posts/{time:[0-9]+}", ApiUserRequiredActivity(getPostsSince, false)).Methods("GET")
|
||||
@@ -60,75 +59,6 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
func createValetPost(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
tchan := Srv.Store.Team().Get(c.Session.TeamId)
|
||||
|
||||
post := model.PostFromJson(r.Body)
|
||||
if post == nil {
|
||||
c.SetInvalidParam("createValetPost", "post")
|
||||
return
|
||||
}
|
||||
|
||||
cchan := Srv.Store.Channel().CheckOpenChannelPermissions(c.Session.TeamId, post.ChannelId)
|
||||
|
||||
// Any one with access to the team can post as valet to any open channel
|
||||
if !c.HasPermissionsToChannel(cchan, "createValetPost") {
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure this team has the valet feature enabled
|
||||
if tResult := <-tchan; tResult.Err != nil {
|
||||
c.Err = model.NewAppError("createValetPost", "Could not find the team for this session, team_id="+c.Session.TeamId, "")
|
||||
return
|
||||
} else {
|
||||
if !tResult.Data.(*model.Team).AllowValet {
|
||||
c.Err = model.NewAppError("createValetPost", "The valet feature is currently turned off. Please contact your team administrator for details.", "")
|
||||
c.Err.StatusCode = http.StatusNotImplemented
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if rp, err := CreateValetPost(c, post); err != nil {
|
||||
c.Err = err
|
||||
|
||||
if strings.Contains(c.Err.Message, "parameter") {
|
||||
c.Err.StatusCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
return
|
||||
} else {
|
||||
w.Write([]byte(rp.ToJson()))
|
||||
}
|
||||
}
|
||||
|
||||
func CreateValetPost(c *Context, post *model.Post) (*model.Post, *model.AppError) {
|
||||
post.Hashtags, _ = model.ParseHashtags(post.Message)
|
||||
|
||||
post.Filenames = []string{} // no files allowed in valet posts yet
|
||||
|
||||
if result := <-Srv.Store.User().GetByUsername(c.Session.TeamId, "valet"); result.Err != nil {
|
||||
// if the bot doesn't exist, create it
|
||||
if tresult := <-Srv.Store.Team().Get(c.Session.TeamId); tresult.Err != nil {
|
||||
return nil, tresult.Err
|
||||
} else {
|
||||
post.UserId = (CreateValet(c, tresult.Data.(*model.Team))).Id
|
||||
}
|
||||
} else {
|
||||
post.UserId = result.Data.(*model.User).Id
|
||||
}
|
||||
|
||||
var rpost *model.Post
|
||||
if result := <-Srv.Store.Post().Save(post); result.Err != nil {
|
||||
return nil, result.Err
|
||||
} else {
|
||||
rpost = result.Data.(*model.Post)
|
||||
}
|
||||
|
||||
fireAndForgetNotifications(rpost, c.Session.TeamId, c.GetSiteURL())
|
||||
|
||||
return rpost, nil
|
||||
}
|
||||
|
||||
func CreatePost(c *Context, post *model.Post, doUpdateLastViewed bool) (*model.Post, *model.AppError) {
|
||||
var pchan store.StoreChannel
|
||||
if len(post.RootId) > 0 {
|
||||
|
||||
@@ -123,98 +123,6 @@ func TestCreatePost(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateValetPost(t *testing.T) {
|
||||
Setup()
|
||||
|
||||
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
|
||||
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
|
||||
|
||||
team2 := &model.Team{DisplayName: "Name Team 2", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
|
||||
team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team)
|
||||
|
||||
user1 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"}
|
||||
user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
|
||||
store.Must(Srv.Store.User().VerifyEmail(user1.Id))
|
||||
|
||||
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"}
|
||||
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
|
||||
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
|
||||
|
||||
Client.LoginByEmail(team.Name, user1.Email, "pwd")
|
||||
|
||||
channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
|
||||
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
|
||||
|
||||
channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
|
||||
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
|
||||
|
||||
if utils.Cfg.TeamSettings.AllowValetDefault {
|
||||
post1 := &model.Post{ChannelId: channel1.Id, Message: "#hashtag a" + model.NewId() + "a"}
|
||||
rpost1, err := Client.CreateValetPost(post1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if rpost1.Data.(*model.Post).Message != post1.Message {
|
||||
t.Fatal("message didn't match")
|
||||
}
|
||||
|
||||
if rpost1.Data.(*model.Post).Hashtags != "#hashtag" {
|
||||
t.Fatal("hashtag didn't match")
|
||||
}
|
||||
|
||||
post2 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a", RootId: rpost1.Data.(*model.Post).Id}
|
||||
rpost2, err := Client.CreateValetPost(post2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
post3 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a", RootId: rpost1.Data.(*model.Post).Id, ParentId: rpost2.Data.(*model.Post).Id}
|
||||
_, err = Client.CreateValetPost(post3)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
post4 := &model.Post{ChannelId: "junk", Message: "a" + model.NewId() + "a"}
|
||||
_, err = Client.CreateValetPost(post4)
|
||||
if err.StatusCode != http.StatusForbidden {
|
||||
t.Fatal("Should have been forbidden")
|
||||
}
|
||||
|
||||
Client.LoginByEmail(team.Name, user2.Email, "pwd")
|
||||
post5 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
|
||||
_, err = Client.CreateValetPost(post5)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
user3 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"}
|
||||
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
|
||||
store.Must(Srv.Store.User().VerifyEmail(user3.Id))
|
||||
|
||||
Client.LoginByEmail(team2.Name, user3.Email, "pwd")
|
||||
|
||||
channel3 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team2.Id}
|
||||
channel3 = Client.Must(Client.CreateChannel(channel3)).Data.(*model.Channel)
|
||||
|
||||
post6 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
|
||||
_, err = Client.CreateValetPost(post6)
|
||||
if err.StatusCode != http.StatusForbidden {
|
||||
t.Fatal("Should have been forbidden")
|
||||
}
|
||||
|
||||
if _, err = Client.DoApiPost("/channels/"+channel3.Id+"/create", "garbage"); err == nil {
|
||||
t.Fatal("should have been an error")
|
||||
}
|
||||
} else {
|
||||
post1 := &model.Post{ChannelId: channel1.Id, Message: "#hashtag a" + model.NewId() + "a"}
|
||||
_, err := Client.CreateValetPost(post1)
|
||||
if err.StatusCode != http.StatusNotImplemented {
|
||||
t.Fatal("Should have failed with 501 - Not Implemented")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePost(t *testing.T) {
|
||||
Setup()
|
||||
|
||||
|
||||
25
api/team.go
25
api/team.go
@@ -60,7 +60,6 @@ func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
subjectPage.Props["SiteURL"] = c.GetSiteURL()
|
||||
bodyPage := NewServerTemplatePage("signup_team_body")
|
||||
bodyPage.Props["SiteURL"] = c.GetSiteURL()
|
||||
bodyPage.Props["TourUrl"] = utils.Cfg.TeamSettings.TourLink
|
||||
|
||||
props := make(map[string]string)
|
||||
props["email"] = email
|
||||
@@ -124,8 +123,6 @@ func createTeamFromSSO(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
team.AllowValet = utils.Cfg.TeamSettings.AllowValetDefault
|
||||
|
||||
if result := <-Srv.Store.Team().Save(team); result.Err != nil {
|
||||
c.Err = result.Err
|
||||
return
|
||||
@@ -207,8 +204,6 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
teamSignup.Team.AllowValet = utils.Cfg.TeamSettings.AllowValetDefault
|
||||
|
||||
if result := <-Srv.Store.Team().Save(&teamSignup.Team); result.Err != nil {
|
||||
c.Err = result.Err
|
||||
return
|
||||
@@ -228,13 +223,6 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if teamSignup.Team.AllowValet {
|
||||
CreateValet(c, rteam)
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
InviteMembers(c, rteam, ruser, teamSignup.Invites)
|
||||
|
||||
teamSignup.Team = *rteam
|
||||
@@ -286,13 +274,6 @@ func CreateTeam(c *Context, team *model.Team) *model.Team {
|
||||
return nil
|
||||
}
|
||||
|
||||
if rteam.AllowValet {
|
||||
CreateValet(c, rteam)
|
||||
if c.Err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return rteam
|
||||
}
|
||||
}
|
||||
@@ -301,7 +282,7 @@ func isTreamCreationAllowed(c *Context, email string) bool {
|
||||
|
||||
email = strings.ToLower(email)
|
||||
|
||||
if utils.Cfg.TeamSettings.DisableTeamCreation {
|
||||
if !utils.Cfg.TeamSettings.EnableTeamCreation {
|
||||
c.Err = model.NewAppError("isTreamCreationAllowed", "Team creation has been disabled. Please ask your systems administrator for details.", "")
|
||||
return false
|
||||
}
|
||||
@@ -567,8 +548,6 @@ func updateValetFeature(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
allowValet := allowValetStr == "true"
|
||||
|
||||
teamId := props["team_id"]
|
||||
if len(teamId) > 0 && len(teamId) != 26 {
|
||||
c.SetInvalidParam("updateValetFeature", "team_id")
|
||||
@@ -597,8 +576,6 @@ func updateValetFeature(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
team = tResult.Data.(*model.Team)
|
||||
}
|
||||
|
||||
team.AllowValet = allowValet
|
||||
|
||||
if result := <-Srv.Store.Team().Update(team); result.Err != nil {
|
||||
c.Err = result.Err
|
||||
return
|
||||
|
||||
@@ -330,79 +330,3 @@ func TestGetMyTeam(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateValetFeature(t *testing.T) {
|
||||
Setup()
|
||||
|
||||
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
|
||||
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
|
||||
|
||||
user := &model.User{TeamId: team.Id, Email: "test@nowhere.com", Nickname: "Corey Hulen", Password: "pwd"}
|
||||
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
|
||||
store.Must(Srv.Store.User().VerifyEmail(user.Id))
|
||||
|
||||
user2 := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"}
|
||||
user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
|
||||
store.Must(Srv.Store.User().VerifyEmail(user2.Id))
|
||||
|
||||
team2 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
|
||||
team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team)
|
||||
|
||||
user3 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"}
|
||||
user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
|
||||
store.Must(Srv.Store.User().VerifyEmail(user3.Id))
|
||||
|
||||
Client.LoginByEmail(team.Name, user2.Email, "pwd")
|
||||
|
||||
data := make(map[string]string)
|
||||
data["allow_valet"] = "true"
|
||||
if _, err := Client.UpdateValetFeature(data); err == nil {
|
||||
t.Fatal("Should have errored, not admin")
|
||||
}
|
||||
|
||||
Client.LoginByEmail(team.Name, user.Email, "pwd")
|
||||
|
||||
data["allow_valet"] = ""
|
||||
if _, err := Client.UpdateValetFeature(data); err == nil {
|
||||
t.Fatal("Should have errored, empty allow_valet field")
|
||||
}
|
||||
|
||||
data["allow_valet"] = "true"
|
||||
if _, err := Client.UpdateValetFeature(data); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rteam := Client.Must(Client.GetMyTeam("")).Data.(*model.Team)
|
||||
if rteam.AllowValet != true {
|
||||
t.Fatal("Should have errored - allow valet property not updated")
|
||||
}
|
||||
|
||||
data["team_id"] = "junk"
|
||||
if _, err := Client.UpdateValetFeature(data); err == nil {
|
||||
t.Fatal("Should have errored, junk team id")
|
||||
}
|
||||
|
||||
data["team_id"] = "12345678901234567890123456"
|
||||
if _, err := Client.UpdateValetFeature(data); err == nil {
|
||||
t.Fatal("Should have errored, bad team id")
|
||||
}
|
||||
|
||||
data["team_id"] = team.Id
|
||||
data["allow_valet"] = "false"
|
||||
if _, err := Client.UpdateValetFeature(data); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
rteam = Client.Must(Client.GetMyTeam("")).Data.(*model.Team)
|
||||
if rteam.AllowValet != false {
|
||||
t.Fatal("Should have errored - allow valet property not updated")
|
||||
}
|
||||
|
||||
Client.LoginByEmail(team2.Name, user3.Email, "pwd")
|
||||
|
||||
data["team_id"] = team.Id
|
||||
data["allow_valet"] = "true"
|
||||
if _, err := Client.UpdateValetFeature(data); err == nil {
|
||||
t.Fatal("Should have errored, not part of team")
|
||||
}
|
||||
}
|
||||
|
||||
16
api/user.go
16
api/user.go
@@ -155,19 +155,13 @@ func IsVerifyHashRequired(user *model.User, team *model.Team, hash string) bool
|
||||
return shouldVerifyHash
|
||||
}
|
||||
|
||||
func CreateValet(c *Context, team *model.Team) *model.User {
|
||||
valet := &model.User{}
|
||||
valet.TeamId = team.Id
|
||||
valet.Email = utils.Cfg.EmailSettings.FeedbackEmail
|
||||
valet.EmailVerified = true
|
||||
valet.Username = model.BOT_USERNAME
|
||||
valet.Password = model.NewId()
|
||||
|
||||
return CreateUser(c, team, valet)
|
||||
}
|
||||
|
||||
func CreateUser(c *Context, team *model.Team, user *model.User) *model.User {
|
||||
|
||||
if !utils.Cfg.TeamSettings.EnableUserCreation {
|
||||
c.Err = model.NewAppError("CreateUser", "User creation has been disabled. Please ask your systems administrator for details.", "")
|
||||
return nil
|
||||
}
|
||||
|
||||
channelRole := ""
|
||||
if team.Email == user.Email {
|
||||
user.Roles = model.ROLE_TEAM_ADMIN
|
||||
|
||||
@@ -952,6 +952,7 @@ func TestUserUpdateNotify(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFuzzyUserCreate(t *testing.T) {
|
||||
Setup()
|
||||
|
||||
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
|
||||
rteam, _ := Client.CreateTeam(&team)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"ServiceSettings": {
|
||||
"SiteName": "Mattermost",
|
||||
"Mode": "dev",
|
||||
"AllowTesting": false,
|
||||
"UseSSL": false,
|
||||
@@ -16,12 +15,11 @@
|
||||
"GoogleDeveloperKey": ""
|
||||
},
|
||||
"TeamSettings": {
|
||||
"MaxUsersPerTeam": 150,
|
||||
"AllowPublicLink": true,
|
||||
"AllowValetDefault": false,
|
||||
"TourLink": "",
|
||||
"SiteName": "Mattermost",
|
||||
"MaxUsersPerTeam": 50,
|
||||
"DefaultThemeColor": "#2389D7",
|
||||
"DisableTeamCreation": false,
|
||||
"EnableTeamCreation": true,
|
||||
"EnableUserCreation": true,
|
||||
"RestrictCreationToDomains": ""
|
||||
},
|
||||
"SqlSettings": {
|
||||
@@ -44,6 +42,7 @@
|
||||
"ImageSettings": {
|
||||
"DriverName": "local",
|
||||
"Directory": "./data/",
|
||||
"EnablePublicLink": true,
|
||||
"ThumbnailWidth": 120,
|
||||
"ThumbnailHeight": 100,
|
||||
"PreviewWidth": 1024,
|
||||
|
||||
@@ -20,7 +20,6 @@ const (
|
||||
)
|
||||
|
||||
type ServiceSettings struct {
|
||||
SiteName string
|
||||
Mode string
|
||||
AllowTesting bool
|
||||
UseSSL bool
|
||||
@@ -68,6 +67,7 @@ type LogSettings struct {
|
||||
type ImageSettings struct {
|
||||
DriverName string
|
||||
Directory string
|
||||
EnablePublicLink bool
|
||||
ThumbnailWidth uint
|
||||
ThumbnailHeight uint
|
||||
PreviewWidth uint
|
||||
@@ -113,12 +113,11 @@ type PrivacySettings struct {
|
||||
}
|
||||
|
||||
type TeamSettings struct {
|
||||
SiteName string
|
||||
MaxUsersPerTeam int
|
||||
AllowPublicLink bool
|
||||
AllowValetDefault bool
|
||||
TourLink string
|
||||
DefaultThemeColor string
|
||||
DisableTeamCreation bool
|
||||
EnableTeamCreation bool
|
||||
EnableUserCreation bool
|
||||
RestrictCreationToDomains string
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ type Team struct {
|
||||
Type string `json:"type"`
|
||||
CompanyName string `json:"company_name"`
|
||||
AllowedDomains string `json:"allowed_domains"`
|
||||
AllowValet bool `json:"allow_valet"`
|
||||
}
|
||||
|
||||
type Invites struct {
|
||||
|
||||
@@ -311,26 +311,21 @@ func (ss SqlStore) CreateColumnIfNotExists(tableName string, columnName string,
|
||||
}
|
||||
}
|
||||
|
||||
// func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool {
|
||||
func (ss SqlStore) RemoveColumnIfExists(tableName string, columnName string) bool {
|
||||
|
||||
// // XXX TODO FIXME this should be removed after 0.6.0
|
||||
// if utils.Cfg.SqlSettings.DriverName == "postgres" {
|
||||
// return false
|
||||
// }
|
||||
if !ss.DoesColumnExist(tableName, columnName) {
|
||||
return false
|
||||
}
|
||||
|
||||
// if !ss.DoesColumnExist(tableName, columnName) {
|
||||
// return false
|
||||
// }
|
||||
_, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
|
||||
if err != nil {
|
||||
l4g.Critical("Failed to drop column %v", err)
|
||||
time.Sleep(time.Second)
|
||||
panic("Failed to drop column " + err.Error())
|
||||
}
|
||||
|
||||
// _, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
|
||||
// if err != nil {
|
||||
// l4g.Critical("Failed to drop column %v", err)
|
||||
// time.Sleep(time.Second)
|
||||
// panic("Failed to drop column " + err.Error())
|
||||
// }
|
||||
|
||||
// return true
|
||||
// }
|
||||
return true
|
||||
}
|
||||
|
||||
// func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ func NewSqlTeamStore(sqlStore *SqlStore) TeamStore {
|
||||
}
|
||||
|
||||
func (s SqlTeamStore) UpgradeSchemaIfNeeded() {
|
||||
s.RemoveColumnIfExists("Teams", "AllowValet")
|
||||
}
|
||||
|
||||
func (s SqlTeamStore) CreateIndexesIfNotExists() {
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestUserStoreSave(t *testing.T) {
|
||||
t.Fatal("should be unique username")
|
||||
}
|
||||
|
||||
for i := 0; i < 150; i++ {
|
||||
for i := 0; i < 50; i++ {
|
||||
u1.Id = ""
|
||||
u1.Email = model.NewId()
|
||||
u1.Username = model.NewId()
|
||||
|
||||
@@ -173,7 +173,7 @@ func getClientProperties(c *model.Config) map[string]string {
|
||||
props["BuildDate"] = model.BuildDate
|
||||
props["BuildHash"] = model.BuildHash
|
||||
|
||||
props["SiteName"] = c.ServiceSettings.SiteName
|
||||
props["SiteName"] = c.TeamSettings.SiteName
|
||||
props["AnalyticsUrl"] = c.ServiceSettings.AnalyticsUrl
|
||||
props["EnableOAuthServiceProvider"] = strconv.FormatBool(c.ServiceSettings.EnableOAuthServiceProvider)
|
||||
props["SegmentDeveloperKey"] = c.ServiceSettings.SegmentDeveloperKey
|
||||
@@ -186,11 +186,10 @@ func getClientProperties(c *model.Config) map[string]string {
|
||||
props["AllowSignUpWithGitLab"] = strconv.FormatBool(c.GitLabSettings.Allow)
|
||||
|
||||
props["ShowEmailAddress"] = strconv.FormatBool(c.PrivacySettings.ShowEmailAddress)
|
||||
props["AllowPublicLink"] = strconv.FormatBool(c.TeamSettings.AllowPublicLink)
|
||||
|
||||
props["EnablePublicLink"] = strconv.FormatBool(c.ImageSettings.EnablePublicLink)
|
||||
props["ProfileHeight"] = fmt.Sprintf("%v", c.ImageSettings.ProfileHeight)
|
||||
props["ProfileWidth"] = fmt.Sprintf("%v", c.ImageSettings.ProfileWidth)
|
||||
props["ProfileWidth"] = fmt.Sprintf("%v", c.ImageSettings.ProfileWidth)
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ var PrivacySettingsTab = require('./privacy_settings.jsx');
|
||||
var RateSettingsTab = require('./rate_settings.jsx');
|
||||
var GitLabSettingsTab = require('./gitlab_settings.jsx');
|
||||
var SqlSettingsTab = require('./sql_settings.jsx');
|
||||
var TeamSettingsTab = require('./team_settings.jsx');
|
||||
|
||||
|
||||
export default class AdminController extends React.Component {
|
||||
constructor(props) {
|
||||
@@ -24,7 +26,7 @@ export default class AdminController extends React.Component {
|
||||
|
||||
this.state = {
|
||||
config: null,
|
||||
selected: 'sql_settings'
|
||||
selected: 'team_settings'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -68,6 +70,8 @@ export default class AdminController extends React.Component {
|
||||
tab = <GitLabSettingsTab config={this.state.config} />;
|
||||
} else if (this.state.selected === 'sql_settings') {
|
||||
tab = <SqlSettingsTab config={this.state.config} />;
|
||||
} else if (this.state.selected === 'team_settings') {
|
||||
tab = <TeamSettingsTab config={this.state.config} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,15 @@ export default class AdminSidebar extends React.Component {
|
||||
<ul className='nav nav-pills nav-stacked'>
|
||||
<li>
|
||||
<ul className='nav nav__sub-menu'>
|
||||
<li>
|
||||
<a
|
||||
href='#'
|
||||
className={this.isSelected('team_settings')}
|
||||
onClick={this.handleClick.bind(this, 'team_settings')}
|
||||
>
|
||||
{'Team Settings'}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href='#'
|
||||
|
||||
@@ -39,6 +39,7 @@ export default class ImageSettings extends React.Component {
|
||||
config.ImageSettings.AmazonS3SecretAccessKey = React.findDOMNode(this.refs.AmazonS3SecretAccessKey).value;
|
||||
config.ImageSettings.AmazonS3Bucket = React.findDOMNode(this.refs.AmazonS3Bucket).value;
|
||||
config.ImageSettings.AmazonS3Region = React.findDOMNode(this.refs.AmazonS3Region).value;
|
||||
config.ImageSettings.EnablePublicLink = React.findDOMNode(this.refs.EnablePublicLink).checked;
|
||||
|
||||
var thumbnailWidth = 120;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.ThumbnailWidth).value, 10))) {
|
||||
@@ -390,6 +391,39 @@ export default class ImageSettings extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='EnablePublicLink'
|
||||
>
|
||||
{'Share Public File Link: '}
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='EnablePublicLink'
|
||||
value='true'
|
||||
ref='EnablePublicLink'
|
||||
defaultChecked={this.props.config.ImageSettings.EnablePublicLink}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
{'true'}
|
||||
</label>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='EnablePublicLink'
|
||||
value='false'
|
||||
defaultChecked={!this.props.config.ImageSettings.EnablePublicLink}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
{'false'}
|
||||
</label>
|
||||
<p className='help-text'>{'Allow users to share public links to files and images.'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<div className='col-sm-12'>
|
||||
{serverError}
|
||||
|
||||
257
web/react/components/admin_console/team_settings.jsx
Normal file
257
web/react/components/admin_console/team_settings.jsx
Normal file
@@ -0,0 +1,257 @@
|
||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
var Client = require('../../utils/client.jsx');
|
||||
var AsyncClient = require('../../utils/async_client.jsx');
|
||||
|
||||
export default class TeamSettings extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleSubmit = this.handleSubmit.bind(this);
|
||||
|
||||
this.state = {
|
||||
saveNeeded: false,
|
||||
serverError: null
|
||||
};
|
||||
}
|
||||
|
||||
handleChange() {
|
||||
var s = {saveNeeded: true, serverError: this.state.serverError};
|
||||
this.setState(s);
|
||||
}
|
||||
|
||||
handleSubmit(e) {
|
||||
e.preventDefault();
|
||||
$('#save-button').button('loading');
|
||||
|
||||
var config = this.props.config;
|
||||
config.TeamSettings.SiteName = React.findDOMNode(this.refs.SiteName).value.trim();
|
||||
config.TeamSettings.DefaultThemeColor = React.findDOMNode(this.refs.DefaultThemeColor).value.trim();
|
||||
config.TeamSettings.RestrictCreationToDomains = React.findDOMNode(this.refs.RestrictCreationToDomains).value.trim();
|
||||
config.TeamSettings.EnableTeamCreation = React.findDOMNode(this.refs.EnableTeamCreation).checked;
|
||||
config.TeamSettings.EnableUserCreation = React.findDOMNode(this.refs.EnableUserCreation).checked;
|
||||
|
||||
var MaxUsersPerTeam = 50;
|
||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.MaxUsersPerTeam).value, 10))) {
|
||||
MaxUsersPerTeam = parseInt(React.findDOMNode(this.refs.MaxUsersPerTeam).value, 10);
|
||||
}
|
||||
config.TeamSettings.MaxUsersPerTeam = MaxUsersPerTeam;
|
||||
React.findDOMNode(this.refs.MaxUsersPerTeam).value = MaxUsersPerTeam;
|
||||
|
||||
Client.saveConfig(
|
||||
config,
|
||||
() => {
|
||||
AsyncClient.getConfig();
|
||||
this.setState({
|
||||
serverError: null,
|
||||
saveNeeded: false
|
||||
});
|
||||
$('#save-button').button('reset');
|
||||
},
|
||||
(err) => {
|
||||
this.setState({
|
||||
serverError: err.message,
|
||||
saveNeeded: true
|
||||
});
|
||||
$('#save-button').button('reset');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
var serverError = '';
|
||||
if (this.state.serverError) {
|
||||
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
|
||||
}
|
||||
|
||||
var saveClass = 'btn';
|
||||
if (this.state.saveNeeded) {
|
||||
saveClass = 'btn btn-primary';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='wrapper--fixed'>
|
||||
|
||||
<h3>{'Team Settings'}</h3>
|
||||
<form
|
||||
className='form-horizontal'
|
||||
role='form'
|
||||
>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='SiteName'
|
||||
>
|
||||
{'Site Name:'}
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='SiteName'
|
||||
ref='SiteName'
|
||||
placeholder='Ex "Mattermost"'
|
||||
defaultValue={this.props.config.TeamSettings.SiteName}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<p className='help-text'>{'Name of service shown in login screens and UI.'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='MaxUsersPerTeam'
|
||||
>
|
||||
{'Max Users Per Team:'}
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='MaxUsersPerTeam'
|
||||
ref='MaxUsersPerTeam'
|
||||
placeholder='Ex "25"'
|
||||
defaultValue={this.props.config.TeamSettings.MaxUsersPerTeam}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<p className='help-text'>{'Maximum number of users per team.'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='DefaultThemeColor'
|
||||
>
|
||||
{'Default Theme Color:'}
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='DefaultThemeColor'
|
||||
ref='DefaultThemeColor'
|
||||
placeholder='Ex "#2389D7"'
|
||||
defaultValue={this.props.config.TeamSettings.DefaultThemeColor}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<p className='help-text'>{'Default theme color for team sites.'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='EnableTeamCreation'
|
||||
>
|
||||
{'Enable Team Creation: '}
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='EnableTeamCreation'
|
||||
value='true'
|
||||
ref='EnableTeamCreation'
|
||||
defaultChecked={this.props.config.TeamSettings.EnableTeamCreation}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
{'true'}
|
||||
</label>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='EnableTeamCreation'
|
||||
value='false'
|
||||
defaultChecked={!this.props.config.TeamSettings.EnableTeamCreation}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
{'false'}
|
||||
</label>
|
||||
<p className='help-text'>{'When false the ability to create teams is disabled. The create team button displays error when pressed.'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='EnableUserCreation'
|
||||
>
|
||||
{'Enable User Creation: '}
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='EnableUserCreation'
|
||||
value='true'
|
||||
ref='EnableUserCreation'
|
||||
defaultChecked={this.props.config.TeamSettings.EnableUserCreation}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
{'true'}
|
||||
</label>
|
||||
<label className='radio-inline'>
|
||||
<input
|
||||
type='radio'
|
||||
name='EnableUserCreation'
|
||||
value='false'
|
||||
defaultChecked={!this.props.config.TeamSettings.EnableUserCreation}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
{'false'}
|
||||
</label>
|
||||
<p className='help-text'>{'When false the ability to create accounts is disabled. The create account button displays error when pressed.'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<label
|
||||
className='control-label col-sm-4'
|
||||
htmlFor='RestrictCreationToDomains'
|
||||
>
|
||||
{'Restrict Creation To Domains:'}
|
||||
</label>
|
||||
<div className='col-sm-8'>
|
||||
<input
|
||||
type='text'
|
||||
className='form-control'
|
||||
id='RestrictCreationToDomains'
|
||||
ref='RestrictCreationToDomains'
|
||||
placeholder='Ex "corp.mattermost.com, mattermost.org"'
|
||||
defaultValue={this.props.config.TeamSettings.RestrictCreationToDomains}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
<p className='help-text'>{'Teams can only be created from a specific domain (e.g. "mattermost.org") or list of comma-separated domains (e.g. "corp.mattermost.com, mattermost.org").'}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='form-group'>
|
||||
<div className='col-sm-12'>
|
||||
{serverError}
|
||||
<button
|
||||
disabled={!this.state.saveNeeded}
|
||||
type='submit'
|
||||
className={saveClass}
|
||||
onClick={this.handleSubmit}
|
||||
id='save-button'
|
||||
data-loading-text={'<span class=\'glyphicon glyphicon-refresh glyphicon-refresh-animate\'></span> Saving Config...'}
|
||||
>
|
||||
{'Save'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TeamSettings.propTypes = {
|
||||
config: React.PropTypes.object
|
||||
};
|
||||
@@ -300,7 +300,7 @@ export default class ViewImageModal extends React.Component {
|
||||
}
|
||||
|
||||
var publicLink = '';
|
||||
if (global.window.config.AllowPublicLink === 'true') {
|
||||
if (global.window.config.EnablePublicLink === 'true') {
|
||||
publicLink = (
|
||||
<div>
|
||||
<a
|
||||
|
||||
@@ -25,7 +25,7 @@ type HtmlTemplatePage api.Page
|
||||
func NewHtmlTemplatePage(templateName string, title string) *HtmlTemplatePage {
|
||||
|
||||
if len(title) > 0 {
|
||||
title = utils.Cfg.ServiceSettings.SiteName + " - " + title
|
||||
title = utils.Cfg.TeamSettings.SiteName + " - " + title
|
||||
}
|
||||
|
||||
props := make(map[string]string)
|
||||
|
||||
Reference in New Issue
Block a user