focalboard/server/app/auth.go

189 lines
4.8 KiB
Go
Raw Normal View History

2020-11-06 16:46:35 +01:00
package app
import (
2020-12-04 16:03:09 +01:00
"log"
2020-11-06 16:46:35 +01:00
"github.com/google/uuid"
2021-01-26 23:13:46 +01:00
"github.com/mattermost/focalboard/server/model"
"github.com/mattermost/focalboard/server/services/auth"
2021-03-26 19:01:54 +01:00
"github.com/mattermost/focalboard/server/services/store"
2020-11-06 16:46:35 +01:00
"github.com/pkg/errors"
)
2020-12-07 17:04:35 +01:00
// GetSession Get a user active session and refresh the session if is needed
2020-12-02 21:12:14 +01:00
func (a *App) GetSession(token string) (*model.Session, error) {
2021-02-02 21:11:21 +01:00
return a.auth.GetSession(token)
2020-12-02 21:12:14 +01:00
}
2021-02-03 03:15:03 +01:00
// IsValidReadToken validates the read token for a block
2021-03-26 19:01:54 +01:00
func (a *App) IsValidReadToken(c store.Container, blockID string, readToken string) (bool, error) {
return a.auth.IsValidReadToken(c, blockID, readToken)
2021-02-03 03:15:03 +01:00
}
2021-01-27 18:22:33 +01:00
// GetRegisteredUserCount returns the number of registered users
func (a *App) GetRegisteredUserCount() (int, error) {
return a.store.GetRegisteredUserCount()
2021-01-14 01:56:01 +01:00
}
2021-01-27 19:01:24 +01:00
// GetDailyActiveUsers returns the number of daily active users
func (a *App) GetDailyActiveUsers() (int, error) {
secondsAgo := int64(60 * 60 * 24)
return a.store.GetActiveUserCount(secondsAgo)
}
// GetWeeklyActiveUsers returns the number of weekly active users
func (a *App) GetWeeklyActiveUsers() (int, error) {
secondsAgo := int64(60 * 60 * 24 * 7)
return a.store.GetActiveUserCount(secondsAgo)
}
// GetMonthlyActiveUsers returns the number of monthly active users
func (a *App) GetMonthlyActiveUsers() (int, error) {
secondsAgo := int64(60 * 60 * 24 * 30)
return a.store.GetActiveUserCount(secondsAgo)
}
2020-12-07 20:40:16 +01:00
// GetUser Get an existing active user by id
func (a *App) GetUser(ID string) (*model.User, error) {
if len(ID) < 1 {
return nil, errors.New("no user ID")
}
2020-12-07 20:40:16 +01:00
user, err := a.store.GetUserById(ID)
if err != nil {
2021-01-20 18:47:08 +01:00
return nil, errors.Wrap(err, "unable to find user")
2020-12-07 20:40:16 +01:00
}
return user, nil
}
2020-12-07 17:04:35 +01:00
// Login create a new user session if the authentication data is valid
2021-03-21 09:28:26 +01:00
func (a *App) Login(username, email, password, mfaToken string) (string, error) {
2020-11-06 16:46:35 +01:00
var user *model.User
if username != "" {
var err error
user, err = a.store.GetUserByUsername(username)
if err != nil {
return "", errors.Wrap(err, "invalid username or password")
}
}
if user == nil && email != "" {
var err error
user, err = a.store.GetUserByEmail(email)
if err != nil {
return "", errors.Wrap(err, "invalid username or password")
}
}
if user == nil {
return "", errors.New("invalid username or password")
}
if !auth.ComparePassword(user.Password, password) {
2021-01-21 19:16:40 +01:00
log.Printf("Invalid password for userID: %s\n", user.ID)
2020-11-06 16:46:35 +01:00
return "", errors.New("invalid username or password")
}
2021-03-26 19:01:54 +01:00
authService := user.AuthService
if authService == "" {
authService = "native"
}
2020-12-02 21:12:14 +01:00
session := model.Session{
2021-03-26 19:01:54 +01:00
ID: uuid.New().String(),
Token: uuid.New().String(),
UserID: user.ID,
AuthService: authService,
Props: map[string]interface{}{},
2020-12-02 21:12:14 +01:00
}
err := a.store.CreateSession(&session)
if err != nil {
return "", errors.Wrap(err, "unable to create session")
}
2020-11-06 16:46:35 +01:00
// TODO: MFA verification
2020-12-02 21:12:14 +01:00
return session.Token, nil
2020-11-06 16:46:35 +01:00
}
2020-12-07 17:04:35 +01:00
// RegisterUser create a new user if the provided data is valid
2021-03-21 09:28:26 +01:00
func (a *App) RegisterUser(username, email, password string) error {
2020-11-06 16:46:35 +01:00
var user *model.User
if username != "" {
var err error
user, err = a.store.GetUserByUsername(username)
if err == nil && user != nil {
return errors.New("The username already exists")
2020-11-06 16:46:35 +01:00
}
}
if user == nil && email != "" {
var err error
user, err = a.store.GetUserByEmail(email)
if err == nil && user != nil {
return errors.New("The email already exists")
2020-11-06 16:46:35 +01:00
}
}
// TODO: Move this into the config
passwordSettings := auth.PasswordSettings{
MinimumLength: 6,
}
err := auth.IsPasswordValid(password, passwordSettings)
if err != nil {
return errors.Wrap(err, "Invalid password")
}
err = a.store.CreateUser(&model.User{
ID: uuid.New().String(),
Username: username,
Email: email,
Password: auth.HashPassword(password),
MfaSecret: "",
2021-03-26 19:01:54 +01:00
AuthService: a.config.AuthMode,
2020-11-06 16:46:35 +01:00
AuthData: "",
Props: map[string]interface{}{},
})
if err != nil {
return errors.Wrap(err, "Unable to create the new user")
}
return nil
}
2021-03-21 09:28:26 +01:00
func (a *App) UpdateUserPassword(username, password string) error {
err := a.store.UpdateUserPassword(username, auth.HashPassword(password))
if err != nil {
return err
}
return nil
}
2021-01-22 20:28:45 +01:00
2021-03-21 09:28:26 +01:00
func (a *App) ChangePassword(userID, oldPassword, newPassword string) error {
2021-01-21 19:16:40 +01:00
var user *model.User
if userID != "" {
var err error
user, err = a.store.GetUserById(userID)
if err != nil {
return errors.Wrap(err, "invalid username or password")
}
}
if user == nil {
return errors.New("invalid username or password")
}
if !auth.ComparePassword(user.Password, oldPassword) {
log.Printf("Invalid password for userID: %s\n", user.ID)
return errors.New("invalid username or password")
}
err := a.store.UpdateUserPasswordByID(userID, auth.HashPassword(newPassword))
if err != nil {
return errors.Wrap(err, "unable to update password")
}
return nil
}