mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 17:10:10 +00:00
Ombi: Integrate with profiles, Retire user defaults
NOTE: If you previously used the Ombi integration, New ombi users won't be created until you set this up. Ombi settings can be added to a profile in Settings > User Profiles. The "Modify settings" options will now apply to ombi if the selected profile has ombi settings.
This commit is contained in:
parent
c988239fa8
commit
4da1c8c2b6
112
api.go
112
api.go
@ -503,16 +503,9 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
app.err.Printf("%s: Failed to set configuration template (%d): %v", req.Code, status, err)
|
app.err.Printf("%s: Failed to set configuration template (%d): %v", req.Code, status, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
|
||||||
if req.Email != "" {
|
|
||||||
app.storage.emails[id] = EmailAddress{Addr: req.Email, Contact: true}
|
|
||||||
app.storage.storeEmails()
|
|
||||||
}
|
|
||||||
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||||
app.storage.loadOmbiTemplate()
|
if profile.Ombi != nil && len(profile.Ombi) != 0 {
|
||||||
if len(app.storage.ombi_template) != 0 {
|
errors, code, err := app.ombi.NewUser(req.Username, req.Password, req.Email, profile.Ombi)
|
||||||
errors, code, err := app.ombi.NewUser(req.Username, req.Password, req.Email, app.storage.ombi_template)
|
|
||||||
if err != nil || code != 200 {
|
if err != nil || code != 200 {
|
||||||
app.info.Printf("Failed to create Ombi user (%d): %s", code, err)
|
app.info.Printf("Failed to create Ombi user (%d): %s", code, err)
|
||||||
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
|
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
|
||||||
@ -521,6 +514,12 @@ func (app *appContext) newUser(req newUserDTO, confirmed bool) (f errorFunc, suc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
||||||
|
if req.Email != "" {
|
||||||
|
app.storage.emails[id] = EmailAddress{Addr: req.Email, Contact: true}
|
||||||
|
app.storage.storeEmails()
|
||||||
|
}
|
||||||
expiry := time.Time{}
|
expiry := time.Time{}
|
||||||
if invite.UserExpiry {
|
if invite.UserExpiry {
|
||||||
app.storage.usersLock.Lock()
|
app.storage.usersLock.Lock()
|
||||||
@ -1221,6 +1220,7 @@ func (app *appContext) GetProfiles(gc *gin.Context) {
|
|||||||
Admin: p.Admin,
|
Admin: p.Admin,
|
||||||
LibraryAccess: p.LibraryAccess,
|
LibraryAccess: p.LibraryAccess,
|
||||||
FromUser: p.FromUser,
|
FromUser: p.FromUser,
|
||||||
|
Ombi: p.Ombi != nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gc.JSON(200, out)
|
gc.JSON(200, out)
|
||||||
@ -1486,26 +1486,65 @@ func (app *appContext) OmbiUsers(gc *gin.Context) {
|
|||||||
gc.JSON(200, ombiUsersDTO{Users: userlist})
|
gc.JSON(200, ombiUsersDTO{Users: userlist})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Set new user defaults for Ombi accounts.
|
// @Summary Store Ombi user template in an existing profile.
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param ombiUser body ombiUser true "User to source settings from"
|
// @Param ombiUser body ombiUser true "User to source settings from"
|
||||||
|
// @Param profile path string true "Name of profile to store in"
|
||||||
// @Success 200 {object} boolResponse
|
// @Success 200 {object} boolResponse
|
||||||
|
// @Failure 400 {object} boolResponse
|
||||||
// @Failure 500 {object} stringResponse
|
// @Failure 500 {object} stringResponse
|
||||||
// @Router /ombi/defaults [post]
|
// @Router /profiles/ombi/{profile} [post]
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @tags Ombi
|
// @tags Ombi
|
||||||
func (app *appContext) SetOmbiDefaults(gc *gin.Context) {
|
func (app *appContext) SetOmbiProfile(gc *gin.Context) {
|
||||||
var req ombiUser
|
var req ombiUser
|
||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
|
profileName := gc.Param("profile")
|
||||||
|
profile, ok := app.storage.profiles[profileName]
|
||||||
|
if !ok {
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
template, code, err := app.ombi.TemplateByID(req.ID)
|
template, code, err := app.ombi.TemplateByID(req.ID)
|
||||||
if err != nil || code != 200 || len(template) == 0 {
|
if err != nil || code != 200 || len(template) == 0 {
|
||||||
app.err.Printf("Couldn't get user from Ombi (%d): %v", code, err)
|
app.err.Printf("Couldn't get user from Ombi (%d): %v", code, err)
|
||||||
respond(500, "Couldn't get user", gc)
|
respond(500, "Couldn't get user", gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
app.storage.ombi_template = template
|
profile.Ombi = template
|
||||||
app.storage.storeOmbiTemplate()
|
app.storage.profiles[profileName] = profile
|
||||||
respondBool(200, true, gc)
|
if err := app.storage.storeProfiles(); err != nil {
|
||||||
|
respond(500, "Failed to store profile", gc)
|
||||||
|
app.err.Printf("Failed to store profiles: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respondBool(204, true, gc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Summary Remove ombi user template from a profile.
|
||||||
|
// @Produce json
|
||||||
|
// @Param profile path string true "Name of profile to store in"
|
||||||
|
// @Success 200 {object} boolResponse
|
||||||
|
// @Failure 400 {object} boolResponse
|
||||||
|
// @Failure 500 {object} stringResponse
|
||||||
|
// @Router /profiles/ombi/{profile} [delete]
|
||||||
|
// @Security Bearer
|
||||||
|
// @tags Ombi
|
||||||
|
func (app *appContext) DeleteOmbiProfile(gc *gin.Context) {
|
||||||
|
profileName := gc.Param("profile")
|
||||||
|
profile, ok := app.storage.profiles[profileName]
|
||||||
|
if !ok {
|
||||||
|
respondBool(400, false, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
profile.Ombi = nil
|
||||||
|
app.storage.profiles[profileName] = profile
|
||||||
|
if err := app.storage.storeProfiles(); err != nil {
|
||||||
|
respond(500, "Failed to store profile", gc)
|
||||||
|
app.err.Printf("Failed to store profiles: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
respondBool(204, true, gc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary Modify user's email addresses.
|
// @Summary Modify user's email addresses.
|
||||||
@ -1671,6 +1710,7 @@ func (app *appContext) ApplySettings(gc *gin.Context) {
|
|||||||
var policy mediabrowser.Policy
|
var policy mediabrowser.Policy
|
||||||
var configuration mediabrowser.Configuration
|
var configuration mediabrowser.Configuration
|
||||||
var displayprefs map[string]interface{}
|
var displayprefs map[string]interface{}
|
||||||
|
var ombi map[string]interface{}
|
||||||
if req.From == "profile" {
|
if req.From == "profile" {
|
||||||
app.storage.loadProfiles()
|
app.storage.loadProfiles()
|
||||||
// Check profile exists & isn't empty
|
// Check profile exists & isn't empty
|
||||||
@ -1689,6 +1729,13 @@ func (app *appContext) ApplySettings(gc *gin.Context) {
|
|||||||
displayprefs = app.storage.profiles[req.Profile].Displayprefs
|
displayprefs = app.storage.profiles[req.Profile].Displayprefs
|
||||||
}
|
}
|
||||||
policy = app.storage.profiles[req.Profile].Policy
|
policy = app.storage.profiles[req.Profile].Policy
|
||||||
|
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||||
|
profile := app.storage.profiles[req.Profile]
|
||||||
|
if profile.Ombi != nil && len(profile.Ombi) != 0 {
|
||||||
|
ombi = profile.Ombi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if req.From == "user" {
|
} else if req.From == "user" {
|
||||||
applyingFrom = "user"
|
applyingFrom = "user"
|
||||||
app.jf.CacheExpiry = time.Now()
|
app.jf.CacheExpiry = time.Now()
|
||||||
@ -1714,6 +1761,7 @@ func (app *appContext) ApplySettings(gc *gin.Context) {
|
|||||||
errors := errorListDTO{
|
errors := errorListDTO{
|
||||||
"policy": map[string]string{},
|
"policy": map[string]string{},
|
||||||
"homescreen": map[string]string{},
|
"homescreen": map[string]string{},
|
||||||
|
"ombi": map[string]string{},
|
||||||
}
|
}
|
||||||
/* Jellyfin doesn't seem to like too many of these requests sent in succession
|
/* Jellyfin doesn't seem to like too many of these requests sent in succession
|
||||||
and can crash and mess up its database. Issue #160 says this occurs when more
|
and can crash and mess up its database. Issue #160 says this occurs when more
|
||||||
@ -1735,17 +1783,47 @@ func (app *appContext) ApplySettings(gc *gin.Context) {
|
|||||||
status, err = app.jf.SetConfiguration(id, configuration)
|
status, err = app.jf.SetConfiguration(id, configuration)
|
||||||
errorString := ""
|
errorString := ""
|
||||||
if !(status == 200 || status == 204) || err != nil {
|
if !(status == 200 || status == 204) || err != nil {
|
||||||
errorString += fmt.Sprintf("Configuration %d: %s ", status, err)
|
errorString += fmt.Sprintf("Configuration %d: %v ", status, err)
|
||||||
} else {
|
} else {
|
||||||
status, err = app.jf.SetDisplayPreferences(id, displayprefs)
|
status, err = app.jf.SetDisplayPreferences(id, displayprefs)
|
||||||
if !(status == 200 || status == 204) || err != nil {
|
if !(status == 200 || status == 204) || err != nil {
|
||||||
errorString += fmt.Sprintf("Displayprefs %d: %s ", status, err)
|
errorString += fmt.Sprintf("Displayprefs %d: %v ", status, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if errorString != "" {
|
if errorString != "" {
|
||||||
errors["homescreen"][id] = errorString
|
errors["homescreen"][id] = errorString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ombi != nil {
|
||||||
|
errorString := ""
|
||||||
|
user, status, err := app.getOmbiUser(id)
|
||||||
|
if status != 200 || err != nil {
|
||||||
|
errorString += fmt.Sprintf("Ombi GetUser %d: %v ", status, err)
|
||||||
|
} else {
|
||||||
|
// newUser := ombi
|
||||||
|
// newUser["id"] = user["id"]
|
||||||
|
// newUser["userName"] = user["userName"]
|
||||||
|
// newUser["alias"] = user["alias"]
|
||||||
|
// newUser["emailAddress"] = user["emailAddress"]
|
||||||
|
for k, v := range ombi {
|
||||||
|
switch v.(type) {
|
||||||
|
case map[string]interface{}, []interface{}:
|
||||||
|
user[k] = v
|
||||||
|
default:
|
||||||
|
if v != user[k] {
|
||||||
|
user[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status, err = app.ombi.ModifyUser(user)
|
||||||
|
if status != 200 || err != nil {
|
||||||
|
errorString += fmt.Sprintf("Apply %d: %v ", status, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if errorString != "" {
|
||||||
|
errors["ombi"][id] = errorString
|
||||||
|
}
|
||||||
|
}
|
||||||
if shouldDelay {
|
if shouldDelay {
|
||||||
time.Sleep(250 * time.Millisecond)
|
time.Sleep(250 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
@ -1020,7 +1020,7 @@
|
|||||||
"order": [],
|
"order": [],
|
||||||
"meta": {
|
"meta": {
|
||||||
"name": "Ombi Integration",
|
"name": "Ombi Integration",
|
||||||
"description": "Connect to Ombi to automatically create both Ombi and Jellyfin accounts for new users. You'll need to create a user template for this to work. Once enabled, refresh to see an option in settings for this. To handle password resets for Ombi & Jellyfin, enable \"Use reset link instead of PIN\"."
|
"description": "Connect to Ombi to automatically create both Ombi and Jellyfin accounts for new users. You'll need to add a ombi template to an existing User Profile for accounts to be created, which you can do by refreshing then checking Settings > User Profiles. To handle password resets for Ombi & Jellyfin, enable \"Use reset link instead of PIN\"."
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"enabled": {
|
"enabled": {
|
||||||
|
@ -266,9 +266,9 @@
|
|||||||
<span class="button ~urge !normal mt-half" id="send-pwr-link">{{ .strings.copy }}</span>
|
<span class="button ~urge !normal mt-half" id="send-pwr-link">{{ .strings.copy }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="modal-ombi-defaults" class="modal">
|
<div id="modal-ombi-profile" class="modal">
|
||||||
<form class="modal-content card" id="form-ombi-defaults" href="">
|
<form class="modal-content card" id="form-ombi-defaults" href="">
|
||||||
<span class="heading">{{ .strings.ombiUserDefaults }} <span class="modal-close">×</span></span>
|
<span class="heading">{{ .strings.ombiProfile }} <span class="modal-close">×</span></span>
|
||||||
<p class="content">{{ .strings.ombiUserDefaultsDescription }}</p>
|
<p class="content">{{ .strings.ombiUserDefaultsDescription }}</p>
|
||||||
<div class="select ~neutral !normal mb-1">
|
<div class="select ~neutral !normal mb-1">
|
||||||
<select></select>
|
<select></select>
|
||||||
@ -289,6 +289,9 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>{{ .strings.name }}</th>
|
<th>{{ .strings.name }}</th>
|
||||||
<th>{{ .strings.userProfilesIsDefault }}</th>
|
<th>{{ .strings.userProfilesIsDefault }}</th>
|
||||||
|
{{ if .ombiEnabled }}
|
||||||
|
<th>Ombi</th>
|
||||||
|
{{ end }}
|
||||||
<th>{{ .strings.from }}</th>
|
<th>{{ .strings.from }}</th>
|
||||||
<th>{{ .strings.userProfilesLibraries }}</th>
|
<th>{{ .strings.userProfilesLibraries }}</th>
|
||||||
<th><span class="button ~neutral !high" id="button-profile-create">{{ .strings.create }}</span></th>
|
<th><span class="button ~neutral !high" id="button-profile-create">{{ .strings.create }}</span></th>
|
||||||
|
@ -83,8 +83,8 @@
|
|||||||
"settingsRefreshPage": "Refresh the page in a few seconds.",
|
"settingsRefreshPage": "Refresh the page in a few seconds.",
|
||||||
"settingsRequiredOrRestartMessage": "Note: {n} indicates a required field, {n} indicates changes require a restart.",
|
"settingsRequiredOrRestartMessage": "Note: {n} indicates a required field, {n} indicates changes require a restart.",
|
||||||
"settingsSave": "Save",
|
"settingsSave": "Save",
|
||||||
"ombiUserDefaults": "Ombi user defaults",
|
"ombiProfile": "Ombi user profile",
|
||||||
"ombiUserDefaultsDescription": "Create an Ombi user and configure it, then select it below. It's settings/permissions will be stored and applied to new Ombi users created by jfa-go",
|
"ombiUserDefaultsDescription": "Create an Ombi user and configure it, then select it below. It's settings/permissions will be stored and applied to new Ombi users created by jfa-go when this profile is selected.",
|
||||||
"userProfiles": "User Profiles",
|
"userProfiles": "User Profiles",
|
||||||
"userProfilesDescription": "Profiles are applied to users when they create an account. A profile include library access rights and homescreen layout.",
|
"userProfilesDescription": "Profiles are applied to users when they create an account. A profile include library access rights and homescreen layout.",
|
||||||
"userProfilesIsDefault": "Default",
|
"userProfilesIsDefault": "Default",
|
||||||
@ -120,7 +120,7 @@
|
|||||||
"saveEmail": "Email saved.",
|
"saveEmail": "Email saved.",
|
||||||
"sentAnnouncement": "Announcement sent.",
|
"sentAnnouncement": "Announcement sent.",
|
||||||
"savedAnnouncement": "Announcement saved.",
|
"savedAnnouncement": "Announcement saved.",
|
||||||
"setOmbiDefaults": "Stored ombi defaults.",
|
"setOmbiProfile": "Stored ombi profile.",
|
||||||
"updateApplied": "Update applied, please restart.",
|
"updateApplied": "Update applied, please restart.",
|
||||||
"updateAppliedRefresh": "Update applied, please refresh.",
|
"updateAppliedRefresh": "Update applied, please refresh.",
|
||||||
"telegramVerified": "Telegram account verified.",
|
"telegramVerified": "Telegram account verified.",
|
||||||
@ -141,7 +141,7 @@
|
|||||||
"errorLoadUsers": "Failed to load users.",
|
"errorLoadUsers": "Failed to load users.",
|
||||||
"errorSaveSettings": "Couldn't save settings.",
|
"errorSaveSettings": "Couldn't save settings.",
|
||||||
"errorLoadSettings": "Failed to load settings.",
|
"errorLoadSettings": "Failed to load settings.",
|
||||||
"errorSetOmbiDefaults": "Failed to store ombi defaults.",
|
"errorSetOmbiProfile": "Failed to store ombi profile.",
|
||||||
"errorLoadOmbiUsers": "Failed to load ombi users.",
|
"errorLoadOmbiUsers": "Failed to load ombi users.",
|
||||||
"errorChangedEmailAddress": "Couldn't change email address of {n}.",
|
"errorChangedEmailAddress": "Couldn't change email address of {n}.",
|
||||||
"errorFailureCheckLogs": "Failed (check console/logs)",
|
"errorFailureCheckLogs": "Failed (check console/logs)",
|
||||||
|
@ -71,6 +71,7 @@ type profileDTO struct {
|
|||||||
Admin bool `json:"admin" example:"false"` // Whether profile has admin rights or not
|
Admin bool `json:"admin" example:"false"` // Whether profile has admin rights or not
|
||||||
LibraryAccess string `json:"libraries" example:"all"` // Number of libraries profile has access to
|
LibraryAccess string `json:"libraries" example:"all"` // Number of libraries profile has access to
|
||||||
FromUser string `json:"fromUser" example:"jeff"` // The user the profile is based on
|
FromUser string `json:"fromUser" example:"jeff"` // The user the profile is based on
|
||||||
|
Ombi bool `json:"ombi"` // Whether or not Ombi settings are stored in this profile.
|
||||||
}
|
}
|
||||||
|
|
||||||
type getProfilesDTO struct {
|
type getProfilesDTO struct {
|
||||||
@ -84,8 +85,9 @@ type profileChangeDTO struct {
|
|||||||
|
|
||||||
type newProfileDTO struct {
|
type newProfileDTO struct {
|
||||||
Name string `json:"name" example:"DefaultProfile" binding:"required"` // Name of the profile
|
Name string `json:"name" example:"DefaultProfile" binding:"required"` // Name of the profile
|
||||||
ID string `json:"id" example:"kasdjlaskjd342342" binding:"required"` // ID of user to source settings from
|
ID string `json:"id" example:"ZXhhbXBsZTEyMzQ1Njc4OQo" binding:"required"` // ID of user to source settings from
|
||||||
Homescreen bool `json:"homescreen" example:"true"` // Whether to store homescreen layout or not
|
Homescreen bool `json:"homescreen" example:"true"` // Whether to store homescreen layout or not
|
||||||
|
OmbiID string `json:"ombi_id" example:"ZXhhbXBsZTEyMzQ1Njc4OQo"` // ID of Ombi user to source settings from (optional)
|
||||||
}
|
}
|
||||||
|
|
||||||
type inviteDTO struct {
|
type inviteDTO struct {
|
||||||
|
@ -217,5 +217,6 @@ func (ombi *Ombi) NewUser(username, password, email string, template map[string]
|
|||||||
}
|
}
|
||||||
return lst, code, err
|
return lst, code, err
|
||||||
}
|
}
|
||||||
|
ombi.cacheExpiry = time.Now()
|
||||||
return nil, code, err
|
return nil, code, err
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,8 @@ func (app *appContext) loadRoutes(router *gin.Engine) {
|
|||||||
}
|
}
|
||||||
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||||
api.GET(p+"/ombi/users", app.OmbiUsers)
|
api.GET(p+"/ombi/users", app.OmbiUsers)
|
||||||
api.POST(p+"/ombi/defaults", app.SetOmbiDefaults)
|
api.POST(p+"/profiles/ombi/:profile", app.SetOmbiProfile)
|
||||||
|
api.DELETE(p+"/profiles/ombi/:profile", app.DeleteOmbiProfile)
|
||||||
}
|
}
|
||||||
api.POST(p+"/matrix/login", app.MatrixLogin)
|
api.POST(p+"/matrix/login", app.MatrixLogin)
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ type Profile struct {
|
|||||||
Configuration mediabrowser.Configuration `json:"configuration,omitempty"`
|
Configuration mediabrowser.Configuration `json:"configuration,omitempty"`
|
||||||
Displayprefs map[string]interface{} `json:"displayprefs,omitempty"`
|
Displayprefs map[string]interface{} `json:"displayprefs,omitempty"`
|
||||||
Default bool `json:"default,omitempty"`
|
Default bool `json:"default,omitempty"`
|
||||||
|
Ombi map[string]interface{} `json:"ombi,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Invite struct {
|
type Invite struct {
|
||||||
|
@ -46,8 +46,8 @@ window.availableProfiles = window.availableProfiles || [];
|
|||||||
|
|
||||||
window.modals.settingsRefresh = new Modal(document.getElementById('modal-refresh'));
|
window.modals.settingsRefresh = new Modal(document.getElementById('modal-refresh'));
|
||||||
|
|
||||||
window.modals.ombiDefaults = new Modal(document.getElementById('modal-ombi-defaults'));
|
window.modals.ombiProfile = new Modal(document.getElementById('modal-ombi-profile'));
|
||||||
document.getElementById('form-ombi-defaults').addEventListener('submit', window.modals.ombiDefaults.close);
|
document.getElementById('form-ombi-defaults').addEventListener('submit', window.modals.ombiProfile.close);
|
||||||
|
|
||||||
window.modals.profiles = new Modal(document.getElementById("modal-user-profiles"));
|
window.modals.profiles = new Modal(document.getElementById("modal-user-profiles"));
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { _get, _post, _delete, toggleLoader } from "../modules/common.js";
|
import { _get, _post, _delete, toggleLoader } from "../modules/common.js";
|
||||||
|
import { ombiProfiles } from "../modules/settings.js";
|
||||||
|
|
||||||
interface Profile {
|
interface Profile {
|
||||||
admin: boolean;
|
admin: boolean;
|
||||||
libraries: string;
|
libraries: string;
|
||||||
fromUser: string;
|
fromUser: string;
|
||||||
|
ombi: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
class profile implements Profile {
|
class profile implements Profile {
|
||||||
@ -11,8 +13,10 @@ class profile implements Profile {
|
|||||||
private _name: HTMLElement;
|
private _name: HTMLElement;
|
||||||
private _adminChip: HTMLSpanElement;
|
private _adminChip: HTMLSpanElement;
|
||||||
private _libraries: HTMLTableDataCellElement;
|
private _libraries: HTMLTableDataCellElement;
|
||||||
|
private _ombiButton: HTMLSpanElement;
|
||||||
private _fromUser: HTMLTableDataCellElement;
|
private _fromUser: HTMLTableDataCellElement;
|
||||||
private _defaultRadio: HTMLInputElement;
|
private _defaultRadio: HTMLInputElement;
|
||||||
|
private _ombi: boolean;
|
||||||
|
|
||||||
get name(): string { return this._name.textContent; }
|
get name(): string { return this._name.textContent; }
|
||||||
set name(v: string) { this._name.textContent = v; }
|
set name(v: string) { this._name.textContent = v; }
|
||||||
@ -31,6 +35,21 @@ class profile implements Profile {
|
|||||||
get libraries(): string { return this._libraries.textContent; }
|
get libraries(): string { return this._libraries.textContent; }
|
||||||
set libraries(v: string) { this._libraries.textContent = v; }
|
set libraries(v: string) { this._libraries.textContent = v; }
|
||||||
|
|
||||||
|
get ombi(): boolean { return this._ombi; }
|
||||||
|
set ombi(v: boolean) {
|
||||||
|
if (!window.ombiEnabled) return;
|
||||||
|
this._ombi = v;
|
||||||
|
if (v) {
|
||||||
|
this._ombiButton.textContent = window.lang.strings("delete");
|
||||||
|
this._ombiButton.classList.add("~critical");
|
||||||
|
this._ombiButton.classList.remove("~neutral");
|
||||||
|
} else {
|
||||||
|
this._ombiButton.textContent = window.lang.strings("add");
|
||||||
|
this._ombiButton.classList.add("~neutral");
|
||||||
|
this._ombiButton.classList.remove("~critical");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
get fromUser(): string { return this._fromUser.textContent; }
|
get fromUser(): string { return this._fromUser.textContent; }
|
||||||
set fromUser(v: string) { this._fromUser.textContent = v; }
|
set fromUser(v: string) { this._fromUser.textContent = v; }
|
||||||
|
|
||||||
@ -39,20 +58,28 @@ class profile implements Profile {
|
|||||||
|
|
||||||
constructor(name: string, p: Profile) {
|
constructor(name: string, p: Profile) {
|
||||||
this._row = document.createElement("tr") as HTMLTableRowElement;
|
this._row = document.createElement("tr") as HTMLTableRowElement;
|
||||||
this._row.innerHTML = `
|
let innerHTML = `
|
||||||
<td><b class="profile-name"></b> <span class="profile-admin"></span></td>
|
<td><b class="profile-name"></b> <span class="profile-admin"></span></td>
|
||||||
<td><input type="radio" name="profile-default"></td>
|
<td><input type="radio" name="profile-default"></td>
|
||||||
|
`;
|
||||||
|
if (window.ombiEnabled) innerHTML += `
|
||||||
|
<td><span class="button !normal profile-ombi"></span></td>
|
||||||
|
`;
|
||||||
|
innerHTML += `
|
||||||
<td class="profile-from ellipsis"></td>
|
<td class="profile-from ellipsis"></td>
|
||||||
<td class="profile-libraries"></td>
|
<td class="profile-libraries"></td>
|
||||||
<td><span class="button ~critical !normal">${window.lang.strings("delete")}</span></td>
|
<td><span class="button ~critical !normal">${window.lang.strings("delete")}</span></td>
|
||||||
`;
|
`;
|
||||||
|
this._row.innerHTML = innerHTML;
|
||||||
this._name = this._row.querySelector("b.profile-name");
|
this._name = this._row.querySelector("b.profile-name");
|
||||||
this._adminChip = this._row.querySelector("span.profile-admin") as HTMLSpanElement;
|
this._adminChip = this._row.querySelector("span.profile-admin") as HTMLSpanElement;
|
||||||
this._libraries = this._row.querySelector("td.profile-libraries") as HTMLTableDataCellElement;
|
this._libraries = this._row.querySelector("td.profile-libraries") as HTMLTableDataCellElement;
|
||||||
|
if (window.ombiEnabled)
|
||||||
|
this._ombiButton = this._row.querySelector("span.profile-ombi") as HTMLSpanElement;
|
||||||
this._fromUser = this._row.querySelector("td.profile-from") as HTMLTableDataCellElement;
|
this._fromUser = this._row.querySelector("td.profile-from") as HTMLTableDataCellElement;
|
||||||
this._defaultRadio = this._row.querySelector("input[type=radio]") as HTMLInputElement;
|
this._defaultRadio = this._row.querySelector("input[type=radio]") as HTMLInputElement;
|
||||||
this._defaultRadio.onclick = () => document.dispatchEvent(new CustomEvent("profiles-default", { detail: this.name }));
|
this._defaultRadio.onclick = () => document.dispatchEvent(new CustomEvent("profiles-default", { detail: this.name }));
|
||||||
(this._row.querySelector("span.button") as HTMLSpanElement).onclick = this.delete;
|
(this._row.querySelector("span.\\~critical") as HTMLSpanElement).onclick = this.delete;
|
||||||
|
|
||||||
this.update(name, p);
|
this.update(name, p);
|
||||||
}
|
}
|
||||||
@ -62,8 +89,11 @@ class profile implements Profile {
|
|||||||
this.admin = p.admin;
|
this.admin = p.admin;
|
||||||
this.fromUser = p.fromUser;
|
this.fromUser = p.fromUser;
|
||||||
this.libraries = p.libraries;
|
this.libraries = p.libraries;
|
||||||
|
this.ombi = p.ombi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setOmbiFunc = (ombiFunc: (ombi: boolean) => void) => { this._ombiButton.onclick = () => ombiFunc(this._ombi); }
|
||||||
|
|
||||||
remove = () => { document.dispatchEvent(new CustomEvent("profiles-delete", { detail: this._name })); this._row.remove(); }
|
remove = () => { document.dispatchEvent(new CustomEvent("profiles-delete", { detail: this._name })); this._row.remove(); }
|
||||||
|
|
||||||
delete = () => _delete("/profiles", { "name": this.name }, (req: XMLHttpRequest) => {
|
delete = () => _delete("/profiles", { "name": this.name }, (req: XMLHttpRequest) => {
|
||||||
@ -89,6 +119,7 @@ export class ProfileEditor {
|
|||||||
private _createButton = document.getElementById("button-profile-create") as HTMLSpanElement;
|
private _createButton = document.getElementById("button-profile-create") as HTMLSpanElement;
|
||||||
private _profiles: { [name: string]: profile } = {};
|
private _profiles: { [name: string]: profile } = {};
|
||||||
private _default: string;
|
private _default: string;
|
||||||
|
private _ombiProfiles: ombiProfiles;
|
||||||
|
|
||||||
private _createForm = document.getElementById("form-add-profile") as HTMLFormElement;
|
private _createForm = document.getElementById("form-add-profile") as HTMLFormElement;
|
||||||
private _profileName = document.getElementById("add-profile-name") as HTMLInputElement;
|
private _profileName = document.getElementById("add-profile-name") as HTMLInputElement;
|
||||||
@ -126,6 +157,23 @@ export class ProfileEditor {
|
|||||||
this._profiles[name].update(name, resp.profiles[name]);
|
this._profiles[name].update(name, resp.profiles[name]);
|
||||||
} else {
|
} else {
|
||||||
this._profiles[name] = new profile(name, resp.profiles[name]);
|
this._profiles[name] = new profile(name, resp.profiles[name]);
|
||||||
|
if (window.ombiEnabled)
|
||||||
|
this._profiles[name].setOmbiFunc((ombi: boolean) => {
|
||||||
|
if (ombi) {
|
||||||
|
this._ombiProfiles.delete(name, (req: XMLHttpRequest) => {
|
||||||
|
if (req.readyState == 4) {
|
||||||
|
if (req.status != 204) {
|
||||||
|
window.notifications.customError("errorDeleteOmbi", window.lang.notif("errorUnknown"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._profiles[name].ombi = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
window.modals.profiles.close();
|
||||||
|
this._ombiProfiles.load(name);
|
||||||
|
}
|
||||||
|
});
|
||||||
this._table.appendChild(this._profiles[name].asElement());
|
this._table.appendChild(this._profiles[name].asElement());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,6 +207,9 @@ export class ProfileEditor {
|
|||||||
this.load();
|
this.load();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (window.ombiEnabled)
|
||||||
|
this._ombiProfiles = new ombiProfiles();
|
||||||
|
|
||||||
this._createButton.onclick = () => _get("/users", null, (req: XMLHttpRequest) => {
|
this._createButton.onclick = () => _get("/users", null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
if (req.status == 200 || req.status == 204) {
|
if (req.status == 200 || req.status == 204) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { _get, _post, toggleLoader, addLoader, removeLoader, insertText } from "../modules/common.js";
|
import { _get, _post, _delete, toggleLoader, addLoader, removeLoader, insertText } from "../modules/common.js";
|
||||||
import { Marked } from "@ts-stack/markdown";
|
import { Marked } from "@ts-stack/markdown";
|
||||||
import { stripMarkdown } from "../modules/stripmd.js";
|
import { stripMarkdown } from "../modules/stripmd.js";
|
||||||
|
|
||||||
@ -659,11 +659,6 @@ export class settingsList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
advancedEnableToggle.checked = false;
|
advancedEnableToggle.checked = false;
|
||||||
|
|
||||||
if (window.ombiEnabled) {
|
|
||||||
let ombi = new ombiDefaults();
|
|
||||||
this._sidebar.appendChild(ombi.button());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _addMatrix = () => {
|
private _addMatrix = () => {
|
||||||
@ -762,42 +757,40 @@ interface ombiUser {
|
|||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ombiDefaults {
|
export class ombiProfiles {
|
||||||
private _form: HTMLFormElement;
|
private _form: HTMLFormElement;
|
||||||
private _button: HTMLSpanElement;
|
|
||||||
private _select: HTMLSelectElement;
|
private _select: HTMLSelectElement;
|
||||||
private _users: { [id: string]: string } = {};
|
private _users: { [id: string]: string } = {};
|
||||||
|
private _currentProfile: string;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this._button = document.createElement("span") as HTMLSpanElement;
|
|
||||||
this._button.classList.add("button", "~neutral", "!low", "settings-section-button", "mb-half");
|
|
||||||
this._button.innerHTML = `<span class="flex">${window.lang.strings("ombiUserDefaults")} <i class="ri-link-unlink-m ml-half"></i></span>`;
|
|
||||||
this._button.onclick = this.load;
|
|
||||||
this._form = document.getElementById("form-ombi-defaults") as HTMLFormElement;
|
this._form = document.getElementById("form-ombi-defaults") as HTMLFormElement;
|
||||||
this._form.onsubmit = this.send;
|
this._form.onsubmit = this.send;
|
||||||
this._select = this._form.querySelector("select") as HTMLSelectElement;
|
this._select = this._form.querySelector("select") as HTMLSelectElement;
|
||||||
}
|
}
|
||||||
button = (): HTMLSpanElement => { return this._button; }
|
|
||||||
send = () => {
|
send = () => {
|
||||||
const button = this._form.querySelector("span.submit") as HTMLSpanElement;
|
const button = this._form.querySelector("span.submit") as HTMLSpanElement;
|
||||||
toggleLoader(button);
|
toggleLoader(button);
|
||||||
let resp = {} as ombiUser;
|
let resp = {} as ombiUser;
|
||||||
resp.id = this._select.value;
|
resp.id = this._select.value;
|
||||||
resp.name = this._users[resp.id];
|
resp.name = this._users[resp.id];
|
||||||
_post("/ombi/defaults", resp, (req: XMLHttpRequest) => {
|
_post("/profiles/ombi/" + this._currentProfile, resp, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
toggleLoader(button);
|
toggleLoader(button);
|
||||||
if (req.status == 200 || req.status == 204) {
|
if (req.status == 200 || req.status == 204) {
|
||||||
window.notifications.customSuccess("ombiDefaults", window.lang.notif("setOmbiDefaults"));
|
window.notifications.customSuccess("ombiDefaults", window.lang.notif("setOmbiProfile"));
|
||||||
} else {
|
} else {
|
||||||
window.notifications.customError("ombiDefaults", window.lang.notif("errorSetOmbiDefaults"));
|
window.notifications.customError("ombiDefaults", window.lang.notif("errorSetOmbiProfile"));
|
||||||
}
|
}
|
||||||
window.modals.ombiDefaults.close();
|
window.modals.ombiProfile.close();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
load = () => {
|
delete = (profile: string, post?: (req: XMLHttpRequest) => void) => _delete("/profiles/ombi/" + profile, null, post);
|
||||||
toggleLoader(this._button);
|
|
||||||
|
load = (profile: string) => {
|
||||||
|
this._currentProfile = profile;
|
||||||
_get("/ombi/users", null, (req: XMLHttpRequest) => {
|
_get("/ombi/users", null, (req: XMLHttpRequest) => {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState == 4) {
|
||||||
if (req.status == 200 && "users" in req.response) {
|
if (req.status == 200 && "users" in req.response) {
|
||||||
@ -808,10 +801,8 @@ class ombiDefaults {
|
|||||||
innerHTML += `<option value="${user.id}">${user.name}</option>`;
|
innerHTML += `<option value="${user.id}">${user.name}</option>`;
|
||||||
}
|
}
|
||||||
this._select.innerHTML = innerHTML;
|
this._select.innerHTML = innerHTML;
|
||||||
toggleLoader(this._button);
|
window.modals.ombiProfile.show();
|
||||||
window.modals.ombiDefaults.show();
|
|
||||||
} else {
|
} else {
|
||||||
toggleLoader(this._button);
|
|
||||||
window.notifications.customError("ombiLoadError", window.lang.notif("errorLoadOmbiUsers"))
|
window.notifications.customError("ombiLoadError", window.lang.notif("errorLoadOmbiUsers"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ declare interface Modals {
|
|||||||
deleteUser: Modal;
|
deleteUser: Modal;
|
||||||
settingsRestart: Modal;
|
settingsRestart: Modal;
|
||||||
settingsRefresh: Modal;
|
settingsRefresh: Modal;
|
||||||
ombiDefaults?: Modal;
|
ombiProfile?: Modal;
|
||||||
profiles: Modal;
|
profiles: Modal;
|
||||||
addProfile: Modal;
|
addProfile: Modal;
|
||||||
announce: Modal;
|
announce: Modal;
|
||||||
|
Loading…
Reference in New Issue
Block a user