@@ -627,6 +627,7 @@ func main() {
|
||||
QueueRepo: queueRepo,
|
||||
UserRepo: userRepo,
|
||||
CollectionRepo: collectionRepo,
|
||||
AuthenticatorRepo: authRepo,
|
||||
UserAuthRepo: userAuthRepo,
|
||||
UserController: userController,
|
||||
FamilyController: familyController,
|
||||
|
||||
@@ -36,6 +36,14 @@ type LogoutSessionReq struct {
|
||||
UserID int64 `json:"userID" binding:"required"`
|
||||
}
|
||||
|
||||
type TokenInfo struct {
|
||||
CreationTime int64 `json:"creationTime"`
|
||||
LastUsedTime int64 `json:"lastUsedTime"`
|
||||
UA string `json:"ua"`
|
||||
IsDeleted bool `json:"isDeleted"`
|
||||
App App `json:"app"`
|
||||
}
|
||||
|
||||
func (a AdminOttReq) Validate() error {
|
||||
if !a.App.IsValid() {
|
||||
return errors.New("invalid app")
|
||||
|
||||
@@ -195,9 +195,10 @@ type TwoFactorRemovalRequest struct {
|
||||
|
||||
type ProfileData struct {
|
||||
// CanDisableEmailMFA is used to decide if client should show disable email MFA option
|
||||
CanDisableEmailMFA bool `json:"canDisableEmailMFA"`
|
||||
IsEmailMFAEnabled bool `json:"isEmailMFAEnabled"`
|
||||
IsTwoFactorEnabled bool `json:"isTwoFactorEnabled"`
|
||||
CanDisableEmailMFA bool `json:"canDisableEmailMFA"`
|
||||
IsEmailMFAEnabled bool `json:"isEmailMFAEnabled"`
|
||||
IsTwoFactorEnabled bool `json:"isTwoFactorEnabled"`
|
||||
PasskeyCount int64 `json:"passkeyCount"`
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/ente-io/museum/pkg/controller/remotestore"
|
||||
"github.com/ente-io/museum/pkg/repo/authenticator"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -39,6 +40,7 @@ type AdminHandler struct {
|
||||
QueueRepo *repo.QueueRepository
|
||||
UserRepo *repo.UserRepository
|
||||
CollectionRepo *repo.CollectionRepository
|
||||
AuthenticatorRepo *authenticator.Repository
|
||||
UserAuthRepo *repo.UserAuthRepository
|
||||
FileRepo *repo.FileRepository
|
||||
BillingRepo *repo.BillingRepository
|
||||
@@ -113,7 +115,7 @@ func (h *AdminHandler) GetUsers(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *AdminHandler) GetUser(c *gin.Context) {
|
||||
e := c.Query("email")
|
||||
e := strings.ToLower(strings.TrimSpace(c.Query("email")))
|
||||
if e == "" {
|
||||
id, err := strconv.ParseInt(c.Query("id"), 10, 64)
|
||||
if err != nil {
|
||||
@@ -571,6 +573,14 @@ func (h *AdminHandler) attachSubscription(ctx *gin.Context, userID int64, respon
|
||||
if err == nil {
|
||||
response["details"] = details
|
||||
}
|
||||
tokenInfos, err := h.UserAuthRepo.GetUserTokenInfo(userID)
|
||||
if err == nil {
|
||||
response["tokens"] = tokenInfos
|
||||
}
|
||||
authEntryCount, err := h.AuthenticatorRepo.GetAuthCodeCount(ctx, userID)
|
||||
if err == nil {
|
||||
response["authCodes"] = authEntryCount
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AdminHandler) ClearOrphanObjects(c *gin.Context) {
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"github.com/ente-io/museum/ente"
|
||||
"github.com/ente-io/museum/ente/details"
|
||||
bonus "github.com/ente-io/museum/ente/storagebonus"
|
||||
"github.com/ente-io/museum/pkg/utils/recover"
|
||||
"github.com/ente-io/museum/pkg/utils/time"
|
||||
"github.com/ente-io/stacktrace"
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -27,6 +26,7 @@ func (c *UserController) GetDetailsV2(ctx *gin.Context, userID int64, fetchMemor
|
||||
var familyData *ente.FamilyMemberResponse
|
||||
var subscription *ente.Subscription
|
||||
var canDisableEmailMFA bool
|
||||
var passkeyCount int64
|
||||
var fileCount, sharedCollectionCount, usage int64
|
||||
var bonus *bonus.ActiveStorageBonus
|
||||
g.Go(func() error {
|
||||
@@ -69,7 +69,12 @@ func (c *UserController) GetDetailsV2(ctx *gin.Context, userID int64, fetchMemor
|
||||
return nil
|
||||
})
|
||||
g.Go(func() error {
|
||||
return recover.Int64ToInt64RecoverWrapper(userID, c.FileRepo.GetUsage, &usage)
|
||||
cnt, err := c.PasskeyRepo.GetPasskeyCount(userID)
|
||||
if err != nil {
|
||||
return stacktrace.Propagate(err, "")
|
||||
}
|
||||
passkeyCount = cnt
|
||||
return nil
|
||||
})
|
||||
|
||||
if fetchMemoryCount {
|
||||
@@ -111,6 +116,7 @@ func (c *UserController) GetDetailsV2(ctx *gin.Context, userID int64, fetchMemor
|
||||
CanDisableEmailMFA: canDisableEmailMFA,
|
||||
IsEmailMFAEnabled: *user.IsEmailMFAEnabled,
|
||||
IsTwoFactorEnabled: *user.IsTwoFactorEnabled,
|
||||
PasskeyCount: passkeyCount,
|
||||
},
|
||||
BonusData: bonus,
|
||||
}
|
||||
|
||||
@@ -89,6 +89,16 @@ func (r *Repository) Update(ctx context.Context, userID int64, req model.UpdateE
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAuthCodeCount returns the count of the authenticator entries for the given user
|
||||
func (r *Repository) GetAuthCodeCount(ctx context.Context, userID int64) (int64, error) {
|
||||
var count int64
|
||||
err := r.DB.QueryRowContext(ctx, `SELECT count(*) FROM authenticator_entity WHERE user_id = $1 and is_deleted = FALSE`, userID).Scan(&count)
|
||||
if err != nil {
|
||||
return 0, stacktrace.Propagate(err, "failed to get auth code count")
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
// GetDiff returns the &{[]ente.TotpEntity} which have been added or
|
||||
// modified after the given sinceTime
|
||||
func (r *Repository) GetDiff(ctx context.Context, userID int64, sinceTime int64, limit int16) ([]model.Entity, error) {
|
||||
|
||||
@@ -101,6 +101,11 @@ func NewRepository(
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Repository) GetPasskeyCount(userID int64) (count int64, err error) {
|
||||
err = r.DB.QueryRow(`SELECT COUNT(*) FROM passkeys WHERE user_id = $1 AND deleted_at IS NULL`, userID).Scan(&count)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Repository) GetUserPasskeys(userID int64) (passkeys []ente.Passkey, err error) {
|
||||
rows, err := r.DB.Query(`
|
||||
SELECT id, user_id, friendly_name, created_at
|
||||
|
||||
@@ -48,6 +48,24 @@ func (repo *UserAuthRepository) GetTokenCreationTime(token string) (int64, error
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (repo *UserAuthRepository) GetUserTokenInfo(userID int64) ([]ente.TokenInfo, error) {
|
||||
rows, err := repo.DB.Query(`SELECT creation_time, last_used_at, user_agent, is_deleted, app FROM tokens WHERE user_id = $1 AND is_deleted = false`, userID)
|
||||
if err != nil {
|
||||
return nil, stacktrace.Propagate(err, "")
|
||||
}
|
||||
defer rows.Close()
|
||||
tokenInfos := make([]ente.TokenInfo, 0)
|
||||
for rows.Next() {
|
||||
var tokenInfo ente.TokenInfo
|
||||
err := rows.Scan(&tokenInfo.CreationTime, &tokenInfo.LastUsedTime, &tokenInfo.UA, &tokenInfo.IsDeleted, &tokenInfo.App)
|
||||
if err != nil {
|
||||
return nil, stacktrace.Propagate(err, "")
|
||||
}
|
||||
tokenInfos = append(tokenInfos, tokenInfo)
|
||||
}
|
||||
return tokenInfos, nil
|
||||
}
|
||||
|
||||
// GetValidOTTs returns the list of OTTs that haven't expired for a given user
|
||||
func (repo *UserAuthRepository) GetValidOTTs(emailHash string, app ente.App) ([]string, error) {
|
||||
rows, err := repo.DB.Query(`SELECT ott FROM otts WHERE email_hash = $1 AND app = $2 AND expiration_time > $3`,
|
||||
|
||||
Reference in New Issue
Block a user