Adding team settings to admin console
Этот коммит содержится в:
@@ -83,7 +83,7 @@ func TestGetConfig(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
cfg := result.Data.(*model.Config)
|
cfg := result.Data.(*model.Config)
|
||||||
|
|
||||||
if len(cfg.ServiceSettings.SiteName) == 0 {
|
if len(cfg.TeamSettings.SiteName) == 0 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ func TestSaveConfig(t *testing.T) {
|
|||||||
} else {
|
} else {
|
||||||
cfg := result.Data.(*model.Config)
|
cfg := result.Data.(*model.Config)
|
||||||
|
|
||||||
if len(cfg.ServiceSettings.SiteName) == 0 {
|
if len(cfg.TeamSettings.SiteName) == 0 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ var Client *model.Client
|
|||||||
func Setup() {
|
func Setup() {
|
||||||
if Srv == nil {
|
if Srv == nil {
|
||||||
utils.LoadConfig("config.json")
|
utils.LoadConfig("config.json")
|
||||||
|
utils.Cfg.TeamSettings.MaxUsersPerTeam = 50
|
||||||
NewServer()
|
NewServer()
|
||||||
StartServer()
|
StartServer()
|
||||||
InitApi()
|
InitApi()
|
||||||
|
|||||||
@@ -471,7 +471,7 @@ func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request)
|
|||||||
m := make(map[string]string)
|
m := make(map[string]string)
|
||||||
m["Message"] = err.Message
|
m["Message"] = err.Message
|
||||||
m["Details"] = err.DetailedError
|
m["Details"] = err.DetailedError
|
||||||
m["SiteName"] = utils.Cfg.ServiceSettings.SiteName
|
m["SiteName"] = utils.Cfg.TeamSettings.SiteName
|
||||||
m["SiteURL"] = SiteURL
|
m["SiteURL"] = SiteURL
|
||||||
|
|
||||||
w.WriteHeader(err.StatusCode)
|
w.WriteHeader(err.StatusCode)
|
||||||
|
|||||||
@@ -447,7 +447,7 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !utils.Cfg.TeamSettings.AllowPublicLink {
|
if !utils.Cfg.ImageSettings.EnablePublicLink {
|
||||||
c.Err = model.NewAppError("getPublicLink", "Public links have been disabled", "")
|
c.Err = model.NewAppError("getPublicLink", "Public links have been disabled", "")
|
||||||
c.Err.StatusCode = http.StatusForbidden
|
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 := r.PathPrefix("/channels/{id:[A-Za-z0-9]+}").Subrouter()
|
||||||
sr.Handle("/create", ApiUserRequired(createPost)).Methods("POST")
|
sr.Handle("/create", ApiUserRequired(createPost)).Methods("POST")
|
||||||
sr.Handle("/valet_create", ApiUserRequired(createValetPost)).Methods("POST")
|
|
||||||
sr.Handle("/update", ApiUserRequired(updatePost)).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/{offset:[0-9]+}/{limit:[0-9]+}", ApiUserRequiredActivity(getPosts, false)).Methods("GET")
|
||||||
sr.Handle("/posts/{time:[0-9]+}", ApiUserRequiredActivity(getPostsSince, 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) {
|
func CreatePost(c *Context, post *model.Post, doUpdateLastViewed bool) (*model.Post, *model.AppError) {
|
||||||
var pchan store.StoreChannel
|
var pchan store.StoreChannel
|
||||||
if len(post.RootId) > 0 {
|
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) {
|
func TestUpdatePost(t *testing.T) {
|
||||||
Setup()
|
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()
|
subjectPage.Props["SiteURL"] = c.GetSiteURL()
|
||||||
bodyPage := NewServerTemplatePage("signup_team_body")
|
bodyPage := NewServerTemplatePage("signup_team_body")
|
||||||
bodyPage.Props["SiteURL"] = c.GetSiteURL()
|
bodyPage.Props["SiteURL"] = c.GetSiteURL()
|
||||||
bodyPage.Props["TourUrl"] = utils.Cfg.TeamSettings.TourLink
|
|
||||||
|
|
||||||
props := make(map[string]string)
|
props := make(map[string]string)
|
||||||
props["email"] = email
|
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 {
|
if result := <-Srv.Store.Team().Save(team); result.Err != nil {
|
||||||
c.Err = result.Err
|
c.Err = result.Err
|
||||||
return
|
return
|
||||||
@@ -207,8 +204,6 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
teamSignup.Team.AllowValet = utils.Cfg.TeamSettings.AllowValetDefault
|
|
||||||
|
|
||||||
if result := <-Srv.Store.Team().Save(&teamSignup.Team); result.Err != nil {
|
if result := <-Srv.Store.Team().Save(&teamSignup.Team); result.Err != nil {
|
||||||
c.Err = result.Err
|
c.Err = result.Err
|
||||||
return
|
return
|
||||||
@@ -228,13 +223,6 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if teamSignup.Team.AllowValet {
|
|
||||||
CreateValet(c, rteam)
|
|
||||||
if c.Err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
InviteMembers(c, rteam, ruser, teamSignup.Invites)
|
InviteMembers(c, rteam, ruser, teamSignup.Invites)
|
||||||
|
|
||||||
teamSignup.Team = *rteam
|
teamSignup.Team = *rteam
|
||||||
@@ -286,13 +274,6 @@ func CreateTeam(c *Context, team *model.Team) *model.Team {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if rteam.AllowValet {
|
|
||||||
CreateValet(c, rteam)
|
|
||||||
if c.Err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rteam
|
return rteam
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,7 +282,7 @@ func isTreamCreationAllowed(c *Context, email string) bool {
|
|||||||
|
|
||||||
email = strings.ToLower(email)
|
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.", "")
|
c.Err = model.NewAppError("isTreamCreationAllowed", "Team creation has been disabled. Please ask your systems administrator for details.", "")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -567,8 +548,6 @@ func updateValetFeature(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
allowValet := allowValetStr == "true"
|
|
||||||
|
|
||||||
teamId := props["team_id"]
|
teamId := props["team_id"]
|
||||||
if len(teamId) > 0 && len(teamId) != 26 {
|
if len(teamId) > 0 && len(teamId) != 26 {
|
||||||
c.SetInvalidParam("updateValetFeature", "team_id")
|
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 = tResult.Data.(*model.Team)
|
||||||
}
|
}
|
||||||
|
|
||||||
team.AllowValet = allowValet
|
|
||||||
|
|
||||||
if result := <-Srv.Store.Team().Update(team); result.Err != nil {
|
if result := <-Srv.Store.Team().Update(team); result.Err != nil {
|
||||||
c.Err = result.Err
|
c.Err = result.Err
|
||||||
return
|
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
|
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 {
|
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 := ""
|
channelRole := ""
|
||||||
if team.Email == user.Email {
|
if team.Email == user.Email {
|
||||||
user.Roles = model.ROLE_TEAM_ADMIN
|
user.Roles = model.ROLE_TEAM_ADMIN
|
||||||
|
|||||||
@@ -952,6 +952,7 @@ func TestUserUpdateNotify(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFuzzyUserCreate(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}
|
team := model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
|
||||||
rteam, _ := Client.CreateTeam(&team)
|
rteam, _ := Client.CreateTeam(&team)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ServiceSettings": {
|
"ServiceSettings": {
|
||||||
"SiteName": "Mattermost",
|
|
||||||
"Mode": "dev",
|
"Mode": "dev",
|
||||||
"AllowTesting": false,
|
"AllowTesting": false,
|
||||||
"UseSSL": false,
|
"UseSSL": false,
|
||||||
@@ -16,12 +15,11 @@
|
|||||||
"GoogleDeveloperKey": ""
|
"GoogleDeveloperKey": ""
|
||||||
},
|
},
|
||||||
"TeamSettings": {
|
"TeamSettings": {
|
||||||
"MaxUsersPerTeam": 150,
|
"SiteName": "Mattermost",
|
||||||
"AllowPublicLink": true,
|
"MaxUsersPerTeam": 50,
|
||||||
"AllowValetDefault": false,
|
|
||||||
"TourLink": "",
|
|
||||||
"DefaultThemeColor": "#2389D7",
|
"DefaultThemeColor": "#2389D7",
|
||||||
"DisableTeamCreation": false,
|
"EnableTeamCreation": true,
|
||||||
|
"EnableUserCreation": true,
|
||||||
"RestrictCreationToDomains": ""
|
"RestrictCreationToDomains": ""
|
||||||
},
|
},
|
||||||
"SqlSettings": {
|
"SqlSettings": {
|
||||||
@@ -44,6 +42,7 @@
|
|||||||
"ImageSettings": {
|
"ImageSettings": {
|
||||||
"DriverName": "local",
|
"DriverName": "local",
|
||||||
"Directory": "./data/",
|
"Directory": "./data/",
|
||||||
|
"EnablePublicLink": true,
|
||||||
"ThumbnailWidth": 120,
|
"ThumbnailWidth": 120,
|
||||||
"ThumbnailHeight": 100,
|
"ThumbnailHeight": 100,
|
||||||
"PreviewWidth": 1024,
|
"PreviewWidth": 1024,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ServiceSettings struct {
|
type ServiceSettings struct {
|
||||||
SiteName string
|
|
||||||
Mode string
|
Mode string
|
||||||
AllowTesting bool
|
AllowTesting bool
|
||||||
UseSSL bool
|
UseSSL bool
|
||||||
@@ -68,6 +67,7 @@ type LogSettings struct {
|
|||||||
type ImageSettings struct {
|
type ImageSettings struct {
|
||||||
DriverName string
|
DriverName string
|
||||||
Directory string
|
Directory string
|
||||||
|
EnablePublicLink bool
|
||||||
ThumbnailWidth uint
|
ThumbnailWidth uint
|
||||||
ThumbnailHeight uint
|
ThumbnailHeight uint
|
||||||
PreviewWidth uint
|
PreviewWidth uint
|
||||||
@@ -113,12 +113,11 @@ type PrivacySettings struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TeamSettings struct {
|
type TeamSettings struct {
|
||||||
|
SiteName string
|
||||||
MaxUsersPerTeam int
|
MaxUsersPerTeam int
|
||||||
AllowPublicLink bool
|
|
||||||
AllowValetDefault bool
|
|
||||||
TourLink string
|
|
||||||
DefaultThemeColor string
|
DefaultThemeColor string
|
||||||
DisableTeamCreation bool
|
EnableTeamCreation bool
|
||||||
|
EnableUserCreation bool
|
||||||
RestrictCreationToDomains string
|
RestrictCreationToDomains string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ type Team struct {
|
|||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
CompanyName string `json:"company_name"`
|
CompanyName string `json:"company_name"`
|
||||||
AllowedDomains string `json:"allowed_domains"`
|
AllowedDomains string `json:"allowed_domains"`
|
||||||
AllowValet bool `json:"allow_valet"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Invites struct {
|
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 !ss.DoesColumnExist(tableName, columnName) {
|
||||||
// if utils.Cfg.SqlSettings.DriverName == "postgres" {
|
return false
|
||||||
// return false
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// if !ss.DoesColumnExist(tableName, columnName) {
|
_, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
|
||||||
// return false
|
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)
|
return true
|
||||||
// if err != nil {
|
}
|
||||||
// l4g.Critical("Failed to drop column %v", err)
|
|
||||||
// time.Sleep(time.Second)
|
|
||||||
// panic("Failed to drop column " + err.Error())
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (ss SqlStore) RenameColumnIfExists(tableName string, oldColumnName string, newColumnName string, colType string) bool {
|
// 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() {
|
func (s SqlTeamStore) UpgradeSchemaIfNeeded() {
|
||||||
|
s.RemoveColumnIfExists("Teams", "AllowValet")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlTeamStore) CreateIndexesIfNotExists() {
|
func (s SqlTeamStore) CreateIndexesIfNotExists() {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func TestUserStoreSave(t *testing.T) {
|
|||||||
t.Fatal("should be unique username")
|
t.Fatal("should be unique username")
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 150; i++ {
|
for i := 0; i < 50; i++ {
|
||||||
u1.Id = ""
|
u1.Id = ""
|
||||||
u1.Email = model.NewId()
|
u1.Email = model.NewId()
|
||||||
u1.Username = model.NewId()
|
u1.Username = model.NewId()
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ func getClientProperties(c *model.Config) map[string]string {
|
|||||||
props["BuildDate"] = model.BuildDate
|
props["BuildDate"] = model.BuildDate
|
||||||
props["BuildHash"] = model.BuildHash
|
props["BuildHash"] = model.BuildHash
|
||||||
|
|
||||||
props["SiteName"] = c.ServiceSettings.SiteName
|
props["SiteName"] = c.TeamSettings.SiteName
|
||||||
props["AnalyticsUrl"] = c.ServiceSettings.AnalyticsUrl
|
props["AnalyticsUrl"] = c.ServiceSettings.AnalyticsUrl
|
||||||
props["EnableOAuthServiceProvider"] = strconv.FormatBool(c.ServiceSettings.EnableOAuthServiceProvider)
|
props["EnableOAuthServiceProvider"] = strconv.FormatBool(c.ServiceSettings.EnableOAuthServiceProvider)
|
||||||
props["SegmentDeveloperKey"] = c.ServiceSettings.SegmentDeveloperKey
|
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["AllowSignUpWithGitLab"] = strconv.FormatBool(c.GitLabSettings.Allow)
|
||||||
|
|
||||||
props["ShowEmailAddress"] = strconv.FormatBool(c.PrivacySettings.ShowEmailAddress)
|
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["ProfileHeight"] = fmt.Sprintf("%v", c.ImageSettings.ProfileHeight)
|
||||||
props["ProfileWidth"] = fmt.Sprintf("%v", c.ImageSettings.ProfileWidth)
|
props["ProfileWidth"] = fmt.Sprintf("%v", c.ImageSettings.ProfileWidth)
|
||||||
props["ProfileWidth"] = fmt.Sprintf("%v", c.ImageSettings.ProfileWidth)
|
|
||||||
|
|
||||||
return props
|
return props
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ var PrivacySettingsTab = require('./privacy_settings.jsx');
|
|||||||
var RateSettingsTab = require('./rate_settings.jsx');
|
var RateSettingsTab = require('./rate_settings.jsx');
|
||||||
var GitLabSettingsTab = require('./gitlab_settings.jsx');
|
var GitLabSettingsTab = require('./gitlab_settings.jsx');
|
||||||
var SqlSettingsTab = require('./sql_settings.jsx');
|
var SqlSettingsTab = require('./sql_settings.jsx');
|
||||||
|
var TeamSettingsTab = require('./team_settings.jsx');
|
||||||
|
|
||||||
|
|
||||||
export default class AdminController extends React.Component {
|
export default class AdminController extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -24,7 +26,7 @@ export default class AdminController extends React.Component {
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
config: null,
|
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} />;
|
tab = <GitLabSettingsTab config={this.state.config} />;
|
||||||
} else if (this.state.selected === 'sql_settings') {
|
} else if (this.state.selected === 'sql_settings') {
|
||||||
tab = <SqlSettingsTab config={this.state.config} />;
|
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'>
|
<ul className='nav nav-pills nav-stacked'>
|
||||||
<li>
|
<li>
|
||||||
<ul className='nav nav__sub-menu'>
|
<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>
|
<li>
|
||||||
<a
|
<a
|
||||||
href='#'
|
href='#'
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export default class ImageSettings extends React.Component {
|
|||||||
config.ImageSettings.AmazonS3SecretAccessKey = React.findDOMNode(this.refs.AmazonS3SecretAccessKey).value;
|
config.ImageSettings.AmazonS3SecretAccessKey = React.findDOMNode(this.refs.AmazonS3SecretAccessKey).value;
|
||||||
config.ImageSettings.AmazonS3Bucket = React.findDOMNode(this.refs.AmazonS3Bucket).value;
|
config.ImageSettings.AmazonS3Bucket = React.findDOMNode(this.refs.AmazonS3Bucket).value;
|
||||||
config.ImageSettings.AmazonS3Region = React.findDOMNode(this.refs.AmazonS3Region).value;
|
config.ImageSettings.AmazonS3Region = React.findDOMNode(this.refs.AmazonS3Region).value;
|
||||||
|
config.ImageSettings.EnablePublicLink = React.findDOMNode(this.refs.EnablePublicLink).checked;
|
||||||
|
|
||||||
var thumbnailWidth = 120;
|
var thumbnailWidth = 120;
|
||||||
if (!isNaN(parseInt(React.findDOMNode(this.refs.ThumbnailWidth).value, 10))) {
|
if (!isNaN(parseInt(React.findDOMNode(this.refs.ThumbnailWidth).value, 10))) {
|
||||||
@@ -390,6 +391,39 @@ export default class ImageSettings extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</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='form-group'>
|
||||||
<div className='col-sm-12'>
|
<div className='col-sm-12'>
|
||||||
{serverError}
|
{serverError}
|
||||||
|
|||||||
257
web/react/components/admin_console/team_settings.jsx
Обычный файл
257
web/react/components/admin_console/team_settings.jsx
Обычный файл
@@ -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 = '';
|
var publicLink = '';
|
||||||
if (global.window.config.AllowPublicLink === 'true') {
|
if (global.window.config.EnablePublicLink === 'true') {
|
||||||
publicLink = (
|
publicLink = (
|
||||||
<div>
|
<div>
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type HtmlTemplatePage api.Page
|
|||||||
func NewHtmlTemplatePage(templateName string, title string) *HtmlTemplatePage {
|
func NewHtmlTemplatePage(templateName string, title string) *HtmlTemplatePage {
|
||||||
|
|
||||||
if len(title) > 0 {
|
if len(title) > 0 {
|
||||||
title = utils.Cfg.ServiceSettings.SiteName + " - " + title
|
title = utils.Cfg.TeamSettings.SiteName + " - " + title
|
||||||
}
|
}
|
||||||
|
|
||||||
props := make(map[string]string)
|
props := make(map[string]string)
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user