mirror of
https://github.com/aunefyren/wrapperr
synced 2024-11-10 05:34:12 +00:00
Sync with Tautulli
Reject stats request for inactive users
This commit is contained in:
parent
d40a0be97a
commit
245957e1bb
11 changed files with 333 additions and 51 deletions
|
@ -7,6 +7,7 @@ import (
|
|||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
)
|
||||
|
||||
var usersPath, _ = filepath.Abs("./config/users.json")
|
||||
|
@ -70,6 +71,10 @@ func GetUsers() (users []models.WrapperrUser, err error) {
|
|||
return users, err
|
||||
}
|
||||
|
||||
sort.Slice(users, func(i, j int) bool {
|
||||
return users[i].UserID < users[j].UserID
|
||||
})
|
||||
|
||||
// Return users object
|
||||
return users, nil
|
||||
}
|
||||
|
|
1
main.go
1
main.go
|
@ -171,6 +171,7 @@ func initRouter(config models.WrapperrConfig) *gin.Engine {
|
|||
admin.POST("/get/cache-statistics", routes.ApiWrapperCacheStatistics)
|
||||
admin.POST("/get/users", routes.ApiGetUsers)
|
||||
admin.POST("/get/users/:userId", routes.ApiGetUser)
|
||||
admin.POST("/sync/users", routes.ApiSyncTautulliUsers)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,34 +85,36 @@ type TautulliEntry struct {
|
|||
|
||||
type TautulliGetUsersReply struct {
|
||||
Response struct {
|
||||
Result string `json:"result"`
|
||||
Message interface{} `json:"message"`
|
||||
Data []struct {
|
||||
RowID int `json:"row_id"`
|
||||
UserID int `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
FriendlyName string `json:"friendly_name"`
|
||||
Thumb interface{} `json:"thumb"`
|
||||
Email string `json:"email"`
|
||||
IsActive int `json:"is_active"`
|
||||
IsAdmin int `json:"is_admin"`
|
||||
IsHomeUser interface{} `json:"is_home_user"`
|
||||
IsAllowSync interface{} `json:"is_allow_sync"`
|
||||
IsRestricted interface{} `json:"is_restricted"`
|
||||
DoNotify int `json:"do_notify"`
|
||||
KeepHistory int `json:"keep_history"`
|
||||
AllowGuest int `json:"allow_guest"`
|
||||
ServerToken interface{} `json:"server_token"`
|
||||
SharedLibraries interface{} `json:"shared_libraries"`
|
||||
FilterAll interface{} `json:"filter_all"`
|
||||
FilterMovies interface{} `json:"filter_movies"`
|
||||
FilterTv interface{} `json:"filter_tv"`
|
||||
FilterMusic interface{} `json:"filter_music"`
|
||||
FilterPhotos interface{} `json:"filter_photos"`
|
||||
} `json:"data"`
|
||||
Result string `json:"result"`
|
||||
Message interface{} `json:"message"`
|
||||
Data []TautulliUser `json:"data"`
|
||||
} `json:"response"`
|
||||
}
|
||||
|
||||
type TautulliUser struct {
|
||||
RowID int `json:"row_id"`
|
||||
UserID int `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
FriendlyName string `json:"friendly_name"`
|
||||
Thumb interface{} `json:"thumb"`
|
||||
Email string `json:"email"`
|
||||
IsActive int `json:"is_active"`
|
||||
IsAdmin int `json:"is_admin"`
|
||||
IsHomeUser interface{} `json:"is_home_user"`
|
||||
IsAllowSync interface{} `json:"is_allow_sync"`
|
||||
IsRestricted interface{} `json:"is_restricted"`
|
||||
DoNotify int `json:"do_notify"`
|
||||
KeepHistory int `json:"keep_history"`
|
||||
AllowGuest int `json:"allow_guest"`
|
||||
ServerToken interface{} `json:"server_token"`
|
||||
SharedLibraries interface{} `json:"shared_libraries"`
|
||||
FilterAll interface{} `json:"filter_all"`
|
||||
FilterMovies interface{} `json:"filter_movies"`
|
||||
FilterTv interface{} `json:"filter_tv"`
|
||||
FilterMusic interface{} `json:"filter_music"`
|
||||
FilterPhotos interface{} `json:"filter_photos"`
|
||||
}
|
||||
|
||||
type TautulliStatusReply struct {
|
||||
Response struct {
|
||||
Result string `json:"result"`
|
||||
|
|
|
@ -7,6 +7,7 @@ type WrapperrUser struct {
|
|||
User string `json:"user_name"`
|
||||
UserID int `json:"user_id"`
|
||||
Email string `json:"user_email"`
|
||||
Active bool `json:"user_active"`
|
||||
Wrappings []WrapperrHistoryEntry `json:"wrappings"`
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package modules
|
||||
|
||||
import (
|
||||
"aunefyren/wrapperr/files"
|
||||
"aunefyren/wrapperr/models"
|
||||
"aunefyren/wrapperr/utilities"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
@ -85,17 +85,47 @@ func TautulliTestConnection(TautulliPort int, TautulliIP string, TautulliHttps b
|
|||
return tautulli_status, nil
|
||||
}
|
||||
|
||||
func TautulliGetUserId(TautulliPort int, TautulliIP string, TautulliHttps bool, TautulliRoot string, TautulliApiKey string, PlexUser string) (userID int, userName string, userFriendlyName string, userEmail string, err error) {
|
||||
func TautulliGetUserId(TautulliPort int, TautulliIP string, TautulliHttps bool, TautulliRoot string, TautulliApiKey string, PlexUser string) (userID int, userName string, userFriendlyName string, userEmail string, userActive bool, err error) {
|
||||
userID = 0
|
||||
userName = ""
|
||||
userEmail = ""
|
||||
userFriendlyName = ""
|
||||
userActive = false
|
||||
err = nil
|
||||
|
||||
body_reply, err := TautulliGetUsers(TautulliPort, TautulliIP, TautulliHttps, TautulliRoot, TautulliApiKey)
|
||||
if err != nil {
|
||||
log.Println("Failed to get users from Tautulli. Error: " + err.Error())
|
||||
return userID, userName, userFriendlyName, userEmail, userActive, errors.New("Failed to get users from Tautulli.")
|
||||
}
|
||||
|
||||
for i := 0; i < len(body_reply.Response.Data); i++ {
|
||||
if body_reply.Response.Data[i].UserID != 0 && (strings.ToLower(body_reply.Response.Data[i].Username) == strings.ToLower(PlexUser) || strings.ToLower(body_reply.Response.Data[i].Email) == strings.ToLower(PlexUser)) {
|
||||
ActiveInt := body_reply.Response.Data[i].IsActive
|
||||
if ActiveInt == 0 {
|
||||
userActive = false
|
||||
} else if ActiveInt == 1 {
|
||||
userActive = true
|
||||
} else {
|
||||
return userID, userName, userFriendlyName, userEmail, userActive, errors.New("Invalid IsActive state in Tautulli.")
|
||||
}
|
||||
|
||||
return body_reply.Response.Data[i].UserID, body_reply.Response.Data[i].Username, body_reply.Response.Data[i].FriendlyName, body_reply.Response.Data[i].Email, userActive, nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Could not find any user that matched the given Plex Identity: '" + PlexUser + "'.")
|
||||
return userID, userName, userEmail, userFriendlyName, userActive, errors.New("Failed to find user.")
|
||||
}
|
||||
|
||||
func TautulliGetUsers(TautulliPort int, TautulliIP string, TautulliHttps bool, TautulliRoot string, TautulliApiKey string) (usersReply models.TautulliGetUsersReply, err error) {
|
||||
usersReply = models.TautulliGetUsersReply{}
|
||||
err = nil
|
||||
|
||||
url_string, err := utilities.BuildURL(TautulliPort, TautulliIP, TautulliHttps, TautulliRoot)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return userID, userName, userFriendlyName, userEmail, errors.New("Failed to build Tautulli connection URL.")
|
||||
log.Println("Failed to build Tautulli connection URL. Error: " + err.Error())
|
||||
return usersReply, errors.New("Failed to build Tautulli connection URL.")
|
||||
}
|
||||
|
||||
url_string = url_string + "api/v2/" + "?apikey=" + TautulliApiKey + "&cmd=get_users"
|
||||
|
@ -105,36 +135,28 @@ func TautulliGetUserId(TautulliPort int, TautulliIP string, TautulliHttps bool,
|
|||
|
||||
req, err := http.NewRequest("GET", url_string, payload)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return userID, userName, userFriendlyName, userEmail, errors.New("Failed to reach Tautulli server.")
|
||||
log.Println("Failed to reach Tautulli server. Error: " + err.Error())
|
||||
return usersReply, errors.New("Failed to reach Tautulli server.")
|
||||
}
|
||||
|
||||
req.Header.Add("Accept", "application/json")
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return userID, userName, userFriendlyName, userEmail, errors.New("Failed to reach Tautulli server.")
|
||||
log.Println("Failed to reach Tautulli server. Error: " + err.Error())
|
||||
return usersReply, errors.New("Failed to reach Tautulli server.")
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
body, err := io.ReadAll(res.Body)
|
||||
|
||||
var body_reply models.TautulliGetUsersReply
|
||||
json.Unmarshal(body, &body_reply)
|
||||
json.Unmarshal(body, &usersReply)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return userID, userName, userFriendlyName, userEmail, errors.New("Failed to parse Tautulli response.")
|
||||
return usersReply, errors.New("Failed to parse Tautulli response.")
|
||||
}
|
||||
|
||||
for i := 0; i < len(body_reply.Response.Data); i++ {
|
||||
if body_reply.Response.Data[i].UserID != 0 && (strings.ToLower(body_reply.Response.Data[i].Username) == strings.ToLower(PlexUser) || strings.ToLower(body_reply.Response.Data[i].Email) == strings.ToLower(PlexUser)) {
|
||||
return body_reply.Response.Data[i].UserID, body_reply.Response.Data[i].Username, body_reply.Response.Data[i].FriendlyName, body_reply.Response.Data[i].Email, nil
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("Could not find any user that matched the given Plex Identity: '" + PlexUser + "'.")
|
||||
return userID, userName, userEmail, userFriendlyName, errors.New("Failed to find user.")
|
||||
return usersReply, err
|
||||
}
|
||||
|
||||
func TautulliDownloadStatistics(TautulliPort int, TautulliIP string, TautulliHttps bool, TautulliRoot string, TautulliApiKey string, TautulliLength int, Libraries string, Grouping string, StartDate string) ([]models.TautulliHistoryItem, error) {
|
||||
|
@ -165,7 +187,7 @@ func TautulliDownloadStatistics(TautulliPort int, TautulliIP string, TautulliHtt
|
|||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
body, err := ioutil.ReadAll(res.Body)
|
||||
body, err := io.ReadAll(res.Body)
|
||||
|
||||
var body_reply models.TautulliGetHistoryReply
|
||||
json.Unmarshal(body, &body_reply)
|
||||
|
@ -177,3 +199,53 @@ func TautulliDownloadStatistics(TautulliPort int, TautulliIP string, TautulliHtt
|
|||
return body_reply.Response.Data.Data, nil
|
||||
|
||||
}
|
||||
|
||||
func TautulliTestEveryServer() (err error) {
|
||||
err = nil
|
||||
|
||||
config, err := files.GetConfig()
|
||||
if err != nil {
|
||||
log.Println("Failed to load Wrapperr configuration. Error: " + err.Error())
|
||||
return errors.New("Failed to load Wrapperr configuration.")
|
||||
}
|
||||
|
||||
for i := 0; i < len(config.TautulliConfig); i++ {
|
||||
log.Println("Checking Tautulli server '" + config.TautulliConfig[i].TautulliName + "'.")
|
||||
tautulli_state, err := TautulliTestConnection(config.TautulliConfig[i].TautulliPort, config.TautulliConfig[i].TautulliIP, config.TautulliConfig[i].TautulliHttps, config.TautulliConfig[i].TautulliRoot, config.TautulliConfig[i].TautulliApiKey)
|
||||
if err != nil {
|
||||
log.Println("Failed to reach Tautulli server '" + config.TautulliConfig[i].TautulliName + "'. Error: " + err.Error())
|
||||
return errors.New("Failed to reach Tautulli server '" + config.TautulliConfig[i].TautulliName + "'.")
|
||||
} else if !tautulli_state {
|
||||
log.Println("Failed to ping Tautulli server '" + config.TautulliConfig[i].TautulliName + "' before retrieving statistics.")
|
||||
return errors.New("Failed to ping Tautulli server '" + config.TautulliConfig[i].TautulliName + "'.")
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func TautulliGetUsersFromEveryServer() (tautulliUsers []models.TautulliUser, err error) {
|
||||
err = nil
|
||||
tautulliUsers = []models.TautulliUser{}
|
||||
|
||||
config, err := files.GetConfig()
|
||||
if err != nil {
|
||||
log.Println("Failed to load Wrapperr configuration. Error: " + err.Error())
|
||||
return tautulliUsers, errors.New("Failed to load Wrapperr configuration.")
|
||||
}
|
||||
|
||||
for i := 0; i < len(config.TautulliConfig); i++ {
|
||||
log.Println("Getting users from Tautulli server '" + config.TautulliConfig[i].TautulliName + "'.")
|
||||
tautulliReply, err := TautulliGetUsers(config.TautulliConfig[i].TautulliPort, config.TautulliConfig[i].TautulliIP, config.TautulliConfig[i].TautulliHttps, config.TautulliConfig[i].TautulliRoot, config.TautulliConfig[i].TautulliApiKey)
|
||||
if err != nil {
|
||||
log.Println("Failed to get users from Tautulli. Error: " + err.Error())
|
||||
return tautulliUsers, errors.New("Failed to get users from Tautulli.")
|
||||
}
|
||||
|
||||
for _, user := range tautulliReply.Response.Data {
|
||||
tautulliUsers = append(tautulliUsers, user)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -58,3 +58,48 @@ func UsersGetUser(userID int) (user models.WrapperrUser, err error) {
|
|||
|
||||
return user, errors.New("User not found.")
|
||||
}
|
||||
|
||||
func UsersUpdateUser(userID int, FriendlyName string, userName string, Email string, ActiveInt int) (err error) {
|
||||
err = nil
|
||||
Active := false
|
||||
|
||||
if ActiveInt == 1 {
|
||||
Active = true
|
||||
} else if ActiveInt == 0 {
|
||||
Active = false
|
||||
} else {
|
||||
return errors.New("Invalid active state found.")
|
||||
}
|
||||
|
||||
users, err := files.GetUsers()
|
||||
if err != nil {
|
||||
log.Println("Failed to get users. Error: " + err.Error())
|
||||
return errors.New("Failed to get users.")
|
||||
}
|
||||
|
||||
userFound := false
|
||||
userIndex := 0
|
||||
for index, foundUser := range users {
|
||||
if foundUser.UserID == userID {
|
||||
userFound = true
|
||||
userIndex = index
|
||||
}
|
||||
}
|
||||
|
||||
if !userFound {
|
||||
return errors.New("Failed to find user based on ID.")
|
||||
}
|
||||
|
||||
users[userIndex].Active = Active
|
||||
users[userIndex].Email = Email
|
||||
users[userIndex].FriendlyName = FriendlyName
|
||||
users[userIndex].User = userName
|
||||
|
||||
err = files.SaveUsers(users)
|
||||
if err != nil {
|
||||
log.Println("Failed to save users. Error: " + err.Error())
|
||||
return errors.New("Failed to save users.")
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -431,3 +431,73 @@ func ApiGetUser(context *gin.Context) {
|
|||
context.JSON(http.StatusOK, gin.H{"message": "Users recieved.", "data": user})
|
||||
return
|
||||
}
|
||||
|
||||
func ApiSyncTautulliUsers(context *gin.Context) {
|
||||
configBool, err := files.GetConfigState()
|
||||
if err != nil {
|
||||
log.Println("Failed to retrieve configuration state. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to retrieve configuration state."})
|
||||
context.Abort()
|
||||
return
|
||||
} else if !configBool {
|
||||
context.JSON(http.StatusBadRequest, gin.H{"error": "Wrapperr is not configured."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
err = modules.TautulliTestEveryServer()
|
||||
if err != nil {
|
||||
log.Println("Failed to test Tautulli server. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to test Tautulli server."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
users, err := modules.TautulliGetUsersFromEveryServer()
|
||||
if err != nil {
|
||||
log.Println("Failed to get users. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get users."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
wrapperrUser, err := modules.UsersGetUser(user.UserID)
|
||||
if err != nil {
|
||||
wrapperrUser = models.WrapperrUser{
|
||||
FriendlyName: user.FriendlyName,
|
||||
User: user.Username,
|
||||
UserID: user.UserID,
|
||||
Email: user.Email,
|
||||
Wrappings: []models.WrapperrHistoryEntry{},
|
||||
}
|
||||
|
||||
err = modules.UsersSaveUserEntry(wrapperrUser)
|
||||
if err != nil {
|
||||
log.Println("Failed to save new user. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save new user."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
err = modules.UsersUpdateUser(user.UserID, user.FriendlyName, user.Username, user.Email, user.IsActive)
|
||||
if err != nil {
|
||||
log.Println("Failed to update user. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update user."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newusers, err := files.GetUsers()
|
||||
if err != nil {
|
||||
log.Println("Failed to new users. Error: " + err.Error())
|
||||
context.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to new users."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
context.JSON(http.StatusOK, gin.H{"message": "Users synced.", "data": newusers})
|
||||
return
|
||||
}
|
||||
|
|
|
@ -184,6 +184,7 @@ func ApiWrapperGetStatistics(context *gin.Context) {
|
|||
var userId int = 0
|
||||
var userEmail string = ""
|
||||
var userFriendlyName = ""
|
||||
var userActive = false
|
||||
|
||||
// Try to authorize bearer token from header
|
||||
authorizationHeader := context.GetHeader("Authorization")
|
||||
|
@ -219,11 +220,12 @@ func ApiWrapperGetStatistics(context *gin.Context) {
|
|||
|
||||
// Check for friendly name using Tautulli
|
||||
for i := 0; i < len(config.TautulliConfig); i++ {
|
||||
_, new_username, new_friendlyname, _, err := modules.TautulliGetUserId(config.TautulliConfig[i].TautulliPort, config.TautulliConfig[i].TautulliIP, config.TautulliConfig[i].TautulliHttps, config.TautulliConfig[i].TautulliRoot, config.TautulliConfig[i].TautulliApiKey, userName)
|
||||
_, new_username, new_friendlyname, _, new_active, err := modules.TautulliGetUserId(config.TautulliConfig[i].TautulliPort, config.TautulliConfig[i].TautulliIP, config.TautulliConfig[i].TautulliHttps, config.TautulliConfig[i].TautulliRoot, config.TautulliConfig[i].TautulliApiKey, userName)
|
||||
|
||||
if err == nil {
|
||||
userName = new_username
|
||||
userFriendlyName = new_friendlyname
|
||||
userActive = new_active
|
||||
}
|
||||
break
|
||||
}
|
||||
|
@ -252,7 +254,7 @@ func ApiWrapperGetStatistics(context *gin.Context) {
|
|||
UserNameFound := false
|
||||
|
||||
for i := 0; i < len(config.TautulliConfig); i++ {
|
||||
new_id, new_username, user_friendlyname, new_email, err := modules.TautulliGetUserId(config.TautulliConfig[i].TautulliPort, config.TautulliConfig[i].TautulliIP, config.TautulliConfig[i].TautulliHttps, config.TautulliConfig[i].TautulliRoot, config.TautulliConfig[i].TautulliApiKey, wrapperr_request.PlexIdentity)
|
||||
new_id, new_username, user_friendlyname, new_email, new_active, err := modules.TautulliGetUserId(config.TautulliConfig[i].TautulliPort, config.TautulliConfig[i].TautulliIP, config.TautulliConfig[i].TautulliHttps, config.TautulliConfig[i].TautulliRoot, config.TautulliConfig[i].TautulliApiKey, wrapperr_request.PlexIdentity)
|
||||
|
||||
if err == nil {
|
||||
UserNameFound = true
|
||||
|
@ -260,6 +262,7 @@ func ApiWrapperGetStatistics(context *gin.Context) {
|
|||
userId = new_id
|
||||
userEmail = new_email
|
||||
userFriendlyName = user_friendlyname
|
||||
userActive = new_active
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,6 +282,12 @@ func ApiWrapperGetStatistics(context *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if !userActive {
|
||||
context.JSON(http.StatusUnauthorized, gin.H{"error": "User is not active."})
|
||||
context.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
wrapperrReply, _, err := modules.GetWrapperStatistics(userName, userFriendlyName, userId, userEmail, config, adminConfig, false, 0)
|
||||
if err != nil {
|
||||
log.Println("Failed to get statistics. Error: " + err.Error())
|
||||
|
|
|
@ -344,7 +344,30 @@ a {
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.user-userid, .user-username, .user-friendlyname, .user-email {
|
||||
.user-userid, .user-active {
|
||||
margin: 0.25em 0.5em;
|
||||
text-align: center;
|
||||
width: 5em;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-active-true {
|
||||
background-color: var(--green);
|
||||
border-radius: 0.25em;
|
||||
width: min-content;
|
||||
padding: 0 0.5em;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.user-active-false {
|
||||
background-color: var(--red);
|
||||
border-radius: 0.25em;
|
||||
width: min-content;
|
||||
padding: 0 0.5em;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.user-username, .user-friendlyname, .user-email {
|
||||
margin: 0.25em 0.5em;
|
||||
text-align: center;
|
||||
width: 15em;
|
||||
|
@ -397,6 +420,14 @@ a {
|
|||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.user-header-short {
|
||||
margin: 0.25em 0.5em;
|
||||
text-align: center;
|
||||
width: 5em;
|
||||
overflow: hidden;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.user-logbutton {
|
||||
width: 4em;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ function get_stats() {
|
|||
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4 && (this.status == 200 || this.status == 400 || this.status == 500)) {
|
||||
if (this.readyState == 4) {
|
||||
try {
|
||||
var result= JSON.parse(this.responseText);
|
||||
} catch(error) {
|
||||
|
|
|
@ -16,6 +16,10 @@ function loadAdminPage() {
|
|||
<hr>
|
||||
</div>
|
||||
|
||||
<div class="form-group newline">
|
||||
<button class="form-control btn" type="submit" name="tautulliSyncButton" id="tautulliSyncButton" onclick="syncTautulli();"><img src="${root}/assets/synchronize.svg" class="btn_logo"></img><p2 id="tautulliSyncButtonImage">Sync with Tautulli</p2></button>
|
||||
</div>
|
||||
|
||||
<div class='form-group newline'>
|
||||
<h3>
|
||||
Wrapperr users
|
||||
|
@ -62,12 +66,13 @@ function getUsers() {
|
|||
function placeUsers(usersArray) {
|
||||
userModule = document.getElementById("users-module")
|
||||
|
||||
userModule.innerHTML += `
|
||||
userModule.innerHTML = `
|
||||
<div class="user-headers">
|
||||
<div class="user-header">ID</div>
|
||||
<div class="user-header-short">ID</div>
|
||||
<div class="user-header">Username</div>
|
||||
<div class="user-header">Friendly name</div>
|
||||
<div class="user-header">Email</div>
|
||||
<div class="user-header-short">Active</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -81,6 +86,13 @@ function placeUsers(usersArray) {
|
|||
`;
|
||||
}
|
||||
|
||||
var active_state_class = ""
|
||||
if(user.user_active) {
|
||||
active_state_class = "user-active-true"
|
||||
} else {
|
||||
active_state_class = "user-active-false"
|
||||
}
|
||||
|
||||
var html = `
|
||||
<div class="user-object">
|
||||
<div class="user-details">
|
||||
|
@ -88,6 +100,11 @@ function placeUsers(usersArray) {
|
|||
<div class="user-username">${user.user_name}</div>
|
||||
<div class="user-friendlyname">${user.user_friendly_name}</div>
|
||||
<div class="user-email">${user.user_email}</div>
|
||||
<div class="user-active">
|
||||
<div class="${active_state_class}">
|
||||
${user.user_active}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${historyDiv}
|
||||
|
@ -150,4 +167,33 @@ function closeModal() {
|
|||
var modalContent = document.getElementById("modal-content-real");
|
||||
modal.style.display = "none";
|
||||
modalContent.innerHTML = "";
|
||||
}
|
||||
|
||||
function syncTautulli() {
|
||||
var xhttp = new XMLHttpRequest();
|
||||
xhttp.onreadystatechange = function() {
|
||||
if (this.readyState == 4) {
|
||||
try {
|
||||
var result= JSON.parse(this.responseText);
|
||||
} catch(error) {
|
||||
alert('Failed to parse API response.');
|
||||
console.log('Failed to parse API response. Error: ' + this.responseText);
|
||||
return;
|
||||
}
|
||||
|
||||
if(result.error) {
|
||||
alert(result.error);
|
||||
} else {
|
||||
placeUsers(result.data);
|
||||
alert(result.message)
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
xhttp.withCredentials = true;
|
||||
xhttp.open("post", api_url + "sync/users");
|
||||
xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
|
||||
xhttp.setRequestHeader("Authorization", cookie);
|
||||
xhttp.send();
|
||||
return;
|
||||
}
|
Loading…
Reference in a new issue