mirror of
https://github.com/mattermost/focalboard.git
synced 2025-01-11 18:13:52 +02:00
Local server on unix port, admin set password
This commit is contained in:
parent
33d5dda7e3
commit
91f51fe0b9
@ -12,5 +12,7 @@
|
||||
"webhook_update": [],
|
||||
"secret": "this-is-a-secret-string",
|
||||
"session_expire_time": 2592000,
|
||||
"session_refresh_time": 18000
|
||||
"session_refresh_time": 18000,
|
||||
"enableLocalMode": true,
|
||||
"localModeSocketLocation": "/var/tmp/octo_local.socket"
|
||||
}
|
||||
|
48
server/api/admin.go
Normal file
48
server/api/admin.go
Normal file
@ -0,0 +1,48 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
type AdminSetPasswordData struct {
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
func (a *API) handleAdminSetPassword(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
username := vars["username"]
|
||||
|
||||
requestBody, err := ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
var requestData AdminSetPasswordData
|
||||
err = json.Unmarshal(requestBody, &requestData)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.Contains(requestData.Password, "") {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": "password is required"}, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = a.app().UpdateUserPassword(username, requestData.Password)
|
||||
if err != nil {
|
||||
errorResponse(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}, err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("AdminSetPassword, username: %s", username)
|
||||
|
||||
jsonBytesResponse(w, http.StatusOK, nil)
|
||||
}
|
@ -59,6 +59,10 @@ func (a *API) RegisterRoutes(r *mux.Router) {
|
||||
r.HandleFunc("/api/v1/workspace/regenerate_signup_token", a.sessionRequired(a.handlePostWorkspaceRegenerateSignupToken)).Methods("POST")
|
||||
}
|
||||
|
||||
func (a *API) RegisterAdminRoutes(r *mux.Router) {
|
||||
r.HandleFunc("/api/v1/admin/users/{username}/password", a.handleAdminSetPassword).Methods("POST")
|
||||
}
|
||||
|
||||
func (a *API) handleGetBlocks(w http.ResponseWriter, r *http.Request) {
|
||||
query := r.URL.Query()
|
||||
parentID := query.Get("parent_id")
|
||||
|
@ -132,3 +132,12 @@ func (a *App) RegisterUser(username string, email string, password string) error
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) UpdateUserPassword(username string, password string) error {
|
||||
err := a.store.UpdateUserPassword(username, auth.HashPassword(password))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -1029,6 +1029,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
|
||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -83,10 +83,10 @@ func main() {
|
||||
|
||||
server, err := server.New(config, singleUser)
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServeTLS: ", err)
|
||||
log.Fatal("server.New ERROR: ", err)
|
||||
}
|
||||
|
||||
if err := server.Start(); err != nil {
|
||||
log.Fatal("ListenAndServeTLS: ", err)
|
||||
log.Fatal("server.Start ERROR: ", err)
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/mux"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/mattermost/mattermost-octo-tasks/server/api"
|
||||
@ -26,6 +29,8 @@ import (
|
||||
"github.com/mattermost/mattermost-server/utils"
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
"github.com/mattermost/mattermost-server/v5/services/filesstore"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
@ -37,6 +42,9 @@ type Server struct {
|
||||
telemetry *telemetry.Service
|
||||
logger *zap.Logger
|
||||
cleanUpSessionsTask *scheduler.ScheduledTask
|
||||
|
||||
localRouter *mux.Router
|
||||
localModeServer *http.Server
|
||||
}
|
||||
|
||||
func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
|
||||
@ -68,6 +76,10 @@ func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
|
||||
appBuilder := func() *app.App { return app.New(cfg, store, wsServer, filesBackend, webhookClient) }
|
||||
api := api.NewAPI(appBuilder, singleUser)
|
||||
|
||||
// Local router for admin APIs
|
||||
localRouter := mux.NewRouter()
|
||||
api.RegisterAdminRoutes(localRouter)
|
||||
|
||||
// Init workspace
|
||||
appBuilder().GetRootWorkspace()
|
||||
|
||||
@ -132,6 +144,7 @@ func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
|
||||
filesBackend: filesBackend,
|
||||
telemetry: telemetryService,
|
||||
logger: logger,
|
||||
localRouter: localRouter,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -141,6 +154,12 @@ func (s *Server) Start() error {
|
||||
|
||||
s.webServer.Start(httpServerExitDone)
|
||||
|
||||
if s.config.EnableLocalMode {
|
||||
if err := s.startLocalModeServer(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
s.cleanUpSessionsTask = scheduler.CreateRecurringTask("cleanUpSessions", func() {
|
||||
if err := s.store.CleanUpSessions(s.config.SessionExpireTime); err != nil {
|
||||
s.logger.Error("Unable to clean up the sessions", zap.Error(err))
|
||||
@ -162,6 +181,8 @@ func (s *Server) Shutdown() error {
|
||||
return err
|
||||
}
|
||||
|
||||
s.stopLocalModeServer()
|
||||
|
||||
if s.cleanUpSessionsTask != nil {
|
||||
s.cleanUpSessionsTask.Cancel()
|
||||
}
|
||||
@ -174,3 +195,40 @@ func (s *Server) Shutdown() error {
|
||||
func (s *Server) Config() *config.Configuration {
|
||||
return s.config
|
||||
}
|
||||
|
||||
// Local server
|
||||
|
||||
func (s *Server) startLocalModeServer() error {
|
||||
s.localModeServer = &http.Server{
|
||||
Handler: s.localRouter,
|
||||
}
|
||||
|
||||
// TODO: Close and delete socket file on shutdown
|
||||
syscall.Unlink(s.config.LocalModeSocketLocation)
|
||||
|
||||
socket := s.config.LocalModeSocketLocation
|
||||
unixListener, err := net.Listen("unix", socket)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = os.Chmod(socket, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
log.Println("Starting unix socket server")
|
||||
err = s.localModeServer.Serve(unixListener)
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("Error starting unix socket server: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) stopLocalModeServer() {
|
||||
if s.localModeServer != nil {
|
||||
s.localModeServer.Close()
|
||||
s.localModeServer = nil
|
||||
}
|
||||
}
|
||||
|
@ -13,18 +13,20 @@ const (
|
||||
|
||||
// Configuration is the app configuration stored in a json file.
|
||||
type Configuration struct {
|
||||
ServerRoot string `json:"serverRoot" mapstructure:"serverRoot"`
|
||||
Port int `json:"port" mapstructure:"port"`
|
||||
DBType string `json:"dbtype" mapstructure:"dbtype"`
|
||||
DBConfigString string `json:"dbconfig" mapstructure:"dbconfig"`
|
||||
UseSSL bool `json:"useSSL" mapstructure:"useSSL"`
|
||||
WebPath string `json:"webpath" mapstructure:"webpath"`
|
||||
FilesPath string `json:"filespath" mapstructure:"filespath"`
|
||||
Telemetry bool `json:"telemetry" mapstructure:"telemetry"`
|
||||
WebhookUpdate []string `json:"webhook_update" mapstructure:"webhook_update"`
|
||||
Secret string `json:"secret" mapstructure:"secret"`
|
||||
SessionExpireTime int64 `json:"session_expire_time" mapstructure:"session_expire_time"`
|
||||
SessionRefreshTime int64 `json:"session_refresh_time" mapstructure:"session_refresh_time"`
|
||||
ServerRoot string `json:"serverRoot" mapstructure:"serverRoot"`
|
||||
Port int `json:"port" mapstructure:"port"`
|
||||
DBType string `json:"dbtype" mapstructure:"dbtype"`
|
||||
DBConfigString string `json:"dbconfig" mapstructure:"dbconfig"`
|
||||
UseSSL bool `json:"useSSL" mapstructure:"useSSL"`
|
||||
WebPath string `json:"webpath" mapstructure:"webpath"`
|
||||
FilesPath string `json:"filespath" mapstructure:"filespath"`
|
||||
Telemetry bool `json:"telemetry" mapstructure:"telemetry"`
|
||||
WebhookUpdate []string `json:"webhook_update" mapstructure:"webhook_update"`
|
||||
Secret string `json:"secret" mapstructure:"secret"`
|
||||
SessionExpireTime int64 `json:"session_expire_time" mapstructure:"session_expire_time"`
|
||||
SessionRefreshTime int64 `json:"session_refresh_time" mapstructure:"session_refresh_time"`
|
||||
EnableLocalMode bool `json:"enableLocalMode" mapstructure:"enableLocalMode"`
|
||||
LocalModeSocketLocation string `json:"localModeSocketLocation" mapstructure:"localModeSocketLocation"`
|
||||
}
|
||||
|
||||
// ReadConfigFile read the configuration from the filesystem.
|
||||
@ -41,6 +43,8 @@ func ReadConfigFile() (*Configuration, error) {
|
||||
viper.SetDefault("WebhookUpdate", nil)
|
||||
viper.SetDefault("SessionExpireTime", 60*60*24*30) // 30 days session lifetime
|
||||
viper.SetDefault("SessionRefreshTime", 60*60*5) // 5 minutes session refresh
|
||||
viper.SetDefault("EnableLocalMode", false)
|
||||
viper.SetDefault("LocalModeSocketLocation", "/var/tmp/octo_local.socket")
|
||||
|
||||
err := viper.ReadInConfig() // Find and read the config file
|
||||
if err != nil { // Handle errors reading the config file
|
||||
|
@ -88,8 +88,21 @@ func (s *SQLStore) UpdateUser(user *model.User) error {
|
||||
Set("username", user.Username).
|
||||
Set("email", user.Email).
|
||||
Set("props", propsBytes).
|
||||
Set("update_at", now)
|
||||
Set("update_at", now).
|
||||
Where(sq.Eq{"id": user.ID})
|
||||
|
||||
_, err = query.Exec()
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *SQLStore) UpdateUserPassword(username string, password string) error {
|
||||
now := time.Now().Unix()
|
||||
|
||||
query := s.getQueryBuilder().Update("users").
|
||||
Set("password", password).
|
||||
Set("update_at", now).
|
||||
Where(sq.Eq{"username": username})
|
||||
|
||||
_, err := query.Exec()
|
||||
return err
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ type Store interface {
|
||||
GetUserByUsername(username string) (*model.User, error)
|
||||
CreateUser(user *model.User) error
|
||||
UpdateUser(user *model.User) error
|
||||
UpdateUserPassword(username string, password string) error
|
||||
|
||||
GetSession(token string, expireTime int64) (*model.Session, error)
|
||||
CreateSession(session *model.Session) error
|
||||
|
Loading…
Reference in New Issue
Block a user