mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-28 03:50:10 +00:00
Compare commits
3 Commits
903a61d0f2
...
9bd7fca95e
Author | SHA1 | Date | |
---|---|---|---|
9bd7fca95e | |||
89e70f6f7a | |||
6b25215768 |
51
api.go
51
api.go
@ -271,8 +271,9 @@ func (app *appContext) NewUser(gc *gin.Context) {
|
|||||||
respond(401, "Unknown error", gc)
|
respond(401, "Unknown error", gc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
app.checkInvite(req.Code, true, req.Username)
|
app.storage.loadProfiles()
|
||||||
invite := app.storage.invites[req.Code]
|
invite := app.storage.invites[req.Code]
|
||||||
|
app.checkInvite(req.Code, true, req.Username)
|
||||||
if app.config.Section("notifications").Key("enabled").MustBool(false) {
|
if app.config.Section("notifications").Key("enabled").MustBool(false) {
|
||||||
for address, settings := range invite.Notify {
|
for address, settings := range invite.Notify {
|
||||||
if settings["notify-creation"] {
|
if settings["notify-creation"] {
|
||||||
@ -296,6 +297,7 @@ func (app *appContext) NewUser(gc *gin.Context) {
|
|||||||
id = user["Id"].(string)
|
id = user["Id"].(string)
|
||||||
}
|
}
|
||||||
if invite.Profile != "" {
|
if invite.Profile != "" {
|
||||||
|
app.debug.Printf("Applying settings from profile \"%s\"", invite.Profile)
|
||||||
profile, ok := app.storage.profiles[invite.Profile]
|
profile, ok := app.storage.profiles[invite.Profile]
|
||||||
if !ok {
|
if !ok {
|
||||||
profile = app.storage.profiles["Default"]
|
profile = app.storage.profiles["Default"]
|
||||||
@ -472,7 +474,9 @@ func (app *appContext) SetProfile(gc *gin.Context) {
|
|||||||
func (app *appContext) GetProfiles(gc *gin.Context) {
|
func (app *appContext) GetProfiles(gc *gin.Context) {
|
||||||
app.storage.loadProfiles()
|
app.storage.loadProfiles()
|
||||||
app.debug.Println("Profiles requested")
|
app.debug.Println("Profiles requested")
|
||||||
out := map[string]map[string]interface{}{}
|
out := map[string]interface{}{
|
||||||
|
"default_profile": app.storage.defaultProfile,
|
||||||
|
}
|
||||||
for name, p := range app.storage.profiles {
|
for name, p := range app.storage.profiles {
|
||||||
out[name] = map[string]interface{}{
|
out[name] = map[string]interface{}{
|
||||||
"admin": p.Admin,
|
"admin": p.Admin,
|
||||||
@ -484,6 +488,27 @@ func (app *appContext) GetProfiles(gc *gin.Context) {
|
|||||||
gc.JSON(200, out)
|
gc.JSON(200, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *appContext) SetDefaultProfile(gc *gin.Context) {
|
||||||
|
req := map[string]string{}
|
||||||
|
gc.BindJSON(&req)
|
||||||
|
app.info.Printf("Setting default profile to \"%s\"", req["name"])
|
||||||
|
if _, ok := app.storage.profiles[req["name"]]; !ok {
|
||||||
|
app.err.Printf("Profile not found: \"%s\"", req["name"])
|
||||||
|
respond(500, "Profile not found", gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for name, profile := range app.storage.profiles {
|
||||||
|
if name == req["name"] {
|
||||||
|
profile.Admin = true
|
||||||
|
app.storage.profiles[name] = profile
|
||||||
|
} else {
|
||||||
|
profile.Admin = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
app.storage.defaultProfile = req["name"]
|
||||||
|
gc.JSON(200, map[string]bool{"success": true})
|
||||||
|
}
|
||||||
|
|
||||||
type newProfileReq struct {
|
type newProfileReq struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
@ -584,10 +609,17 @@ func (app *appContext) GetInvites(gc *gin.Context) {
|
|||||||
invites = append(invites, invite)
|
invites = append(invites, invite)
|
||||||
}
|
}
|
||||||
profiles := make([]string, len(app.storage.profiles))
|
profiles := make([]string, len(app.storage.profiles))
|
||||||
i := 0
|
if len(app.storage.profiles) != 0 {
|
||||||
for p := range app.storage.profiles {
|
profiles[0] = app.storage.defaultProfile
|
||||||
profiles[i] = p
|
i := 1
|
||||||
i++
|
if len(app.storage.profiles) > 1 {
|
||||||
|
for p := range app.storage.profiles {
|
||||||
|
if p != app.storage.defaultProfile {
|
||||||
|
profiles[i] = p
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
resp := map[string]interface{}{
|
resp := map[string]interface{}{
|
||||||
"profiles": profiles,
|
"profiles": profiles,
|
||||||
@ -950,8 +982,11 @@ func (app *appContext) ModifyConfig(gc *gin.Context) {
|
|||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
tempConfig, _ := ini.Load(app.config_path)
|
tempConfig, _ := ini.Load(app.config_path)
|
||||||
for section, settings := range req {
|
for section, settings := range req {
|
||||||
_, err := tempConfig.GetSection(section)
|
if section != "restart-program" {
|
||||||
if section != "restart-program" && err == nil {
|
_, err := tempConfig.GetSection(section)
|
||||||
|
if err != nil {
|
||||||
|
tempConfig.NewSection(section)
|
||||||
|
}
|
||||||
for setting, value := range settings.(map[string]interface{}) {
|
for setting, value := range settings.(map[string]interface{}) {
|
||||||
tempConfig.Section(section).Key(setting).SetValue(value.(string))
|
tempConfig.Section(section).Key(setting).SetValue(value.(string))
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@
|
|||||||
"bs5": {
|
"bs5": {
|
||||||
"name": "Use Bootstrap 5",
|
"name": "Use Bootstrap 5",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": false,
|
"requires_restart": true,
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"value": false,
|
"value": false,
|
||||||
"description": "Use Bootstrap 5 (currently in alpha). This also removes the need for jQuery, so the page should load faster."
|
"description": "Use Bootstrap 5 (currently in alpha). This also removes the need for jQuery, so the page should load faster."
|
||||||
@ -608,7 +608,7 @@
|
|||||||
"requires_restart": true,
|
"requires_restart": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "",
|
"value": "",
|
||||||
"description": "Location of stored user policy template (json)."
|
"description": "Deprecated. Location of stored user policy template (json)."
|
||||||
},
|
},
|
||||||
"user_configuration": {
|
"user_configuration": {
|
||||||
"name": "userConfiguration",
|
"name": "userConfiguration",
|
||||||
@ -616,7 +616,7 @@
|
|||||||
"requires_restart": true,
|
"requires_restart": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "",
|
"value": "",
|
||||||
"description": "Location of stored user configuration template (used for setting homescreen layout) (json)"
|
"description": "Deprecated. Location of stored user configuration template (used for setting homescreen layout) (json)"
|
||||||
},
|
},
|
||||||
"user_displayprefs": {
|
"user_displayprefs": {
|
||||||
"name": "displayPreferences",
|
"name": "displayPreferences",
|
||||||
@ -624,7 +624,7 @@
|
|||||||
"requires_restart": true,
|
"requires_restart": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "",
|
"value": "",
|
||||||
"description": "Location of stored displayPreferences template (also used for homescreen layout) (json)"
|
"description": "Deprecated. Location of stored displayPreferences template (also used for homescreen layout) (json)"
|
||||||
},
|
},
|
||||||
"user_profiles": {
|
"user_profiles": {
|
||||||
"name": "User Profiles",
|
"name": "User Profiles",
|
||||||
@ -632,7 +632,7 @@
|
|||||||
"requires_restart": true,
|
"requires_restart": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "",
|
"value": "",
|
||||||
"description": "Location of stored user profiles (encompasses template and homescreen) (json)"
|
"description": "Location of stored user profiles (encompasses template and configuration and displayprefs) (json)"
|
||||||
},
|
},
|
||||||
"custom_css": {
|
"custom_css": {
|
||||||
"name": "Custom CSS",
|
"name": "Custom CSS",
|
||||||
|
@ -216,7 +216,7 @@
|
|||||||
"bs5": {
|
"bs5": {
|
||||||
"name": "Use Bootstrap 5",
|
"name": "Use Bootstrap 5",
|
||||||
"required": false,
|
"required": false,
|
||||||
"requires_restart": false,
|
"requires_restart": true,
|
||||||
"type": "bool",
|
"type": "bool",
|
||||||
"value": false,
|
"value": false,
|
||||||
"description": "Use Bootstrap 5 (currently in alpha). This also removes the need for jQuery, so the page should load faster."
|
"description": "Use Bootstrap 5 (currently in alpha). This also removes the need for jQuery, so the page should load faster."
|
||||||
@ -678,6 +678,7 @@
|
|||||||
"user_template",
|
"user_template",
|
||||||
"user_configuration",
|
"user_configuration",
|
||||||
"user_displayprefs",
|
"user_displayprefs",
|
||||||
|
"user_profiles",
|
||||||
"custom_css"
|
"custom_css"
|
||||||
],
|
],
|
||||||
"meta": {
|
"meta": {
|
||||||
@ -714,7 +715,7 @@
|
|||||||
"requires_restart": true,
|
"requires_restart": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "",
|
"value": "",
|
||||||
"description": "Location of stored user policy template (json)."
|
"description": "Deprecated. Location of stored user policy template (json)."
|
||||||
},
|
},
|
||||||
"user_configuration": {
|
"user_configuration": {
|
||||||
"name": "userConfiguration",
|
"name": "userConfiguration",
|
||||||
@ -722,7 +723,7 @@
|
|||||||
"requires_restart": true,
|
"requires_restart": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "",
|
"value": "",
|
||||||
"description": "Location of stored user configuration template (used for setting homescreen layout) (json)"
|
"description": "Deprecated. Location of stored user configuration template (used for setting homescreen layout) (json)"
|
||||||
},
|
},
|
||||||
"user_displayprefs": {
|
"user_displayprefs": {
|
||||||
"name": "displayPreferences",
|
"name": "displayPreferences",
|
||||||
@ -730,7 +731,15 @@
|
|||||||
"requires_restart": true,
|
"requires_restart": true,
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"value": "",
|
"value": "",
|
||||||
"description": "Location of stored displayPreferences template (also used for homescreen layout) (json)"
|
"description": "Deprecated. Location of stored displayPreferences template (also used for homescreen layout) (json)"
|
||||||
|
},
|
||||||
|
"user_profiles": {
|
||||||
|
"name": "User Profiles",
|
||||||
|
"required": false,
|
||||||
|
"requires_restart": true,
|
||||||
|
"type": "text",
|
||||||
|
"value": "",
|
||||||
|
"description": "Location of stored user profiles (encompasses template and configuration and displayprefs) (json)"
|
||||||
},
|
},
|
||||||
"custom_css": {
|
"custom_css": {
|
||||||
"name": "Custom CSS",
|
"name": "Custom CSS",
|
||||||
|
@ -437,10 +437,11 @@
|
|||||||
<div id="profiles" class="unfocused">
|
<div id="profiles" class="unfocused">
|
||||||
<div class="card card-body">
|
<div class="card card-body">
|
||||||
<p>Profiles are applied to users when they create an account. They include things like access rights and homescreen layout. You can create them here.</p>
|
<p>Profiles are applied to users when they create an account. They include things like access rights and homescreen layout. You can create them here.</p>
|
||||||
<table class="table table-striped table-borderless">
|
<table class="table table-sm table-striped table-borderless">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Name</th>
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Default</th>
|
||||||
<th scope="col">From</th>
|
<th scope="col">From</th>
|
||||||
<th scope="col">Admin?</th>
|
<th scope="col">Admin?</th>
|
||||||
<th scope="col">Libraries</th>
|
<th scope="col">Libraries</th>
|
||||||
|
1
main.go
1
main.go
@ -460,6 +460,7 @@ func start(asDaemon, firstCall bool) {
|
|||||||
api.GET("/getInvites", app.GetInvites)
|
api.GET("/getInvites", app.GetInvites)
|
||||||
api.GET("/getProfiles", app.GetProfiles)
|
api.GET("/getProfiles", app.GetProfiles)
|
||||||
api.POST("/setProfile", app.SetProfile)
|
api.POST("/setProfile", app.SetProfile)
|
||||||
|
api.POST("/setDefaultProfile", app.SetDefaultProfile)
|
||||||
api.POST("/createProfile", app.CreateProfile)
|
api.POST("/createProfile", app.CreateProfile)
|
||||||
api.POST("/deleteProfile", app.DeleteProfile)
|
api.POST("/deleteProfile", app.DeleteProfile)
|
||||||
api.POST("/setNotify", app.SetNotify)
|
api.POST("/setNotify", app.SetNotify)
|
||||||
|
11
storage.go
11
storage.go
@ -12,6 +12,7 @@ type Storage struct {
|
|||||||
invite_path, emails_path, policy_path, configuration_path, displayprefs_path, ombi_path, profiles_path string
|
invite_path, emails_path, policy_path, configuration_path, displayprefs_path, ombi_path, profiles_path string
|
||||||
invites Invites
|
invites Invites
|
||||||
profiles map[string]Profile
|
profiles map[string]Profile
|
||||||
|
defaultProfile string
|
||||||
emails, policy, configuration, displayprefs, ombi_template map[string]interface{}
|
emails, policy, configuration, displayprefs, ombi_template map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ type Profile struct {
|
|||||||
Policy map[string]interface{} `json:"policy,omitempty"`
|
Policy map[string]interface{} `json:"policy,omitempty"`
|
||||||
Configuration map[string]interface{} `json:"configuration,omitempty"`
|
Configuration map[string]interface{} `json:"configuration,omitempty"`
|
||||||
Displayprefs map[string]interface{} `json:"displayprefs,omitempty"`
|
Displayprefs map[string]interface{} `json:"displayprefs,omitempty"`
|
||||||
|
Default bool `json:"default,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Invite struct {
|
type Invite struct {
|
||||||
@ -90,6 +92,9 @@ func (st *Storage) storeOmbiTemplate() error {
|
|||||||
func (st *Storage) loadProfiles() error {
|
func (st *Storage) loadProfiles() error {
|
||||||
err := loadJSON(st.profiles_path, &st.profiles)
|
err := loadJSON(st.profiles_path, &st.profiles)
|
||||||
for name, profile := range st.profiles {
|
for name, profile := range st.profiles {
|
||||||
|
if profile.Default {
|
||||||
|
st.defaultProfile = name
|
||||||
|
}
|
||||||
change := false
|
change := false
|
||||||
if profile.Policy["IsAdministrator"] != nil {
|
if profile.Policy["IsAdministrator"] != nil {
|
||||||
profile.Admin = profile.Policy["IsAdministrator"].(bool)
|
profile.Admin = profile.Policy["IsAdministrator"].(bool)
|
||||||
@ -112,8 +117,10 @@ func (st *Storage) loadProfiles() error {
|
|||||||
st.profiles[name] = profile
|
st.profiles[name] = profile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if st.defaultProfile == "" {
|
||||||
panic(err)
|
for n := range st.profiles {
|
||||||
|
st.defaultProfile = n
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -143,10 +143,12 @@ const populateProfiles = (noTable?: boolean): void => _get("/getProfiles", null,
|
|||||||
if (this.readyState == 4 && this.status == 200) {
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
const profileList = document.getElementById('profileList');
|
const profileList = document.getElementById('profileList');
|
||||||
profileList.textContent = '';
|
profileList.textContent = '';
|
||||||
availableProfiles = [];
|
availableProfiles = [this.response["default_profile"]];
|
||||||
for (let name in this.response) {
|
for (let name in this.response) {
|
||||||
availableProfiles.push(name);
|
if (name != availableProfiles[0]) {
|
||||||
if (!noTable) {
|
availableProfiles.push(name);
|
||||||
|
}
|
||||||
|
if (!noTable && name != "default_profile") {
|
||||||
const profile: Profile = {
|
const profile: Profile = {
|
||||||
Admin: this.response[name]["admin"],
|
Admin: this.response[name]["admin"],
|
||||||
LibraryAccess: this.response[name]["libraries"],
|
LibraryAccess: this.response[name]["libraries"],
|
||||||
@ -154,16 +156,28 @@ const populateProfiles = (noTable?: boolean): void => _get("/getProfiles", null,
|
|||||||
};
|
};
|
||||||
profileList.innerHTML += `
|
profileList.innerHTML += `
|
||||||
<td nowrap="nowrap" class="align-middle"><strong>${name}</strong></td>
|
<td nowrap="nowrap" class="align-middle"><strong>${name}</strong></td>
|
||||||
|
<td nowrap="nowrap" class="align-middle"><input class="${(bsVersion == 5) ? "form-check-input" : ""}" type="radio" name="defaultProfile" onclick="setDefaultProfile('${name}')" ${(name == availableProfiles[0]) ? "checked" : ""}></td>
|
||||||
<td nowrap="nowrap" class="align-middle">${profile.FromUser}</td>
|
<td nowrap="nowrap" class="align-middle">${profile.FromUser}</td>
|
||||||
<td nowrap="nowrap" class="align-middle">${profile.Admin ? "Yes" : "No"}</td>
|
<td nowrap="nowrap" class="align-middle">${profile.Admin ? "Yes" : "No"}</td>
|
||||||
<td nowrap="nowrap" class="align-middle">${profile.LibraryAccess}</td>
|
<td nowrap="nowrap" class="align-middle">${profile.LibraryAccess}</td>
|
||||||
<td nowrap="nowrap" class="align-middle"><button class="btn btn-outline-danger" onclick="deleteProfile('${name}')">Delete</button></td>
|
<td nowrap="nowrap" class="align-middle"><button class="btn btn-outline-danger" id="defaultProfile_${name}" onclick="deleteProfile('${name}')">Delete</button></td>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const setDefaultProfile = (name: string): void => _post("/setDefaultProfile", { "name": name }, function (): void {
|
||||||
|
if (this.readyState == 4) {
|
||||||
|
if (this.status != 200) {
|
||||||
|
(document.getElementById(`defaultProfile_${availableProfiles[0]}`) as HTMLInputElement).checked = true;
|
||||||
|
(document.getElementById(`defaultProfile_${name}`) as HTMLInputElement).checked = false;
|
||||||
|
} else {
|
||||||
|
generateInvites();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const deleteProfile = (name: string): void => _post("/deleteProfile", { "name": name }, function (): void {
|
const deleteProfile = (name: string): void => _post("/deleteProfile", { "name": name }, function (): void {
|
||||||
if (this.readyState == 4 && this.status == 200) {
|
if (this.readyState == 4 && this.status == 200) {
|
||||||
populateProfiles();
|
populateProfiles();
|
||||||
@ -224,10 +238,11 @@ function storeProfile(): void {
|
|||||||
addAttr(button, "btn-primary");
|
addAttr(button, "btn-primary");
|
||||||
rmAttr(button, "btn-success");
|
rmAttr(button, "btn-success");
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
populateProfiles();
|
|
||||||
userDefaultsModal.hide();
|
userDefaultsModal.hide();
|
||||||
|
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
populateProfiles();
|
||||||
|
generateInvites();
|
||||||
} else {
|
} else {
|
||||||
if ("error" in this.response) {
|
if ("error" in this.response) {
|
||||||
button.textContent = this.response["error"];
|
button.textContent = this.response["error"];
|
||||||
|
Loading…
Reference in New Issue
Block a user