mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-23 01:20:11 +00:00
add user button
added create user button for the admin to use.
This commit is contained in:
parent
9213f2a078
commit
d4b94bc9d9
52
api.go
52
api.go
@ -180,6 +180,58 @@ type newUserReq struct {
|
|||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (app *appContext) NewUserAdmin(gc *gin.Context) {
|
||||||
|
var req newUserReq
|
||||||
|
gc.BindJSON(&req)
|
||||||
|
existingUser, _, _ := app.jf.userByName(req.Username, false)
|
||||||
|
if existingUser != nil {
|
||||||
|
msg := fmt.Sprintf("User already exists named %s", req.Username)
|
||||||
|
app.info.Printf("%s New user failed: %s", req.Username, msg)
|
||||||
|
respond(401, msg, gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user, status, err := app.jf.newUser(req.Username, req.Password)
|
||||||
|
if !(status == 200 || status == 204) || err != nil {
|
||||||
|
app.err.Printf("%s New user failed: Jellyfin responded with %d", req.Username, status)
|
||||||
|
respond(401, "Unknown error", gc)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var id string
|
||||||
|
if user["Id"] != nil {
|
||||||
|
id = user["Id"].(string)
|
||||||
|
}
|
||||||
|
if len(app.storage.policy) != 0 {
|
||||||
|
status, err = app.jf.setPolicy(id, app.storage.policy)
|
||||||
|
if !(status == 200 || status == 204) {
|
||||||
|
app.err.Printf("%s: Failed to set user policy: Code %d", req.Username, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(app.storage.configuration) != 0 && len(app.storage.displayprefs) != 0 {
|
||||||
|
status, err = app.jf.setConfiguration(id, app.storage.configuration)
|
||||||
|
if (status == 200 || status == 204) && err == nil {
|
||||||
|
status, err = app.jf.setDisplayPreferences(id, app.storage.displayprefs)
|
||||||
|
} else {
|
||||||
|
app.err.Printf("%s: Failed to set configuration template: Code %d", req.Username, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if app.config.Section("password_resets").Key("enabled").MustBool(false) {
|
||||||
|
app.storage.emails[id] = req.Email
|
||||||
|
app.storage.storeEmails()
|
||||||
|
}
|
||||||
|
if app.config.Section("ombi").Key("enabled").MustBool(false) {
|
||||||
|
app.storage.loadOmbiTemplate()
|
||||||
|
if len(app.storage.ombi_template) != 0 {
|
||||||
|
errors, code, err := app.ombi.newUser(req.Username, req.Password, req.Email, app.storage.ombi_template)
|
||||||
|
if err != nil || code != 200 {
|
||||||
|
app.info.Printf("Failed to create Ombi user (%d): %s", code, err)
|
||||||
|
app.debug.Printf("Errors reported by Ombi: %s", strings.Join(errors, ", "))
|
||||||
|
} else {
|
||||||
|
app.info.Println("Created Ombi user")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (app *appContext) NewUser(gc *gin.Context) {
|
func (app *appContext) NewUser(gc *gin.Context) {
|
||||||
var req newUserReq
|
var req newUserReq
|
||||||
gc.BindJSON(&req)
|
gc.BindJSON(&req)
|
||||||
|
@ -171,8 +171,6 @@ function changeEmail(icon, id) {
|
|||||||
icon.parentNode.appendChild(cross);
|
icon.parentNode.appendChild(cross);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function populateUsers() {
|
function populateUsers() {
|
||||||
const acList = document.getElementById('accountsList');
|
const acList = document.getElementById('accountsList');
|
||||||
acList.innerHTML = `
|
acList.innerHTML = `
|
||||||
@ -292,6 +290,74 @@ document.getElementById('defaultsSource').addEventListener('change', function()
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
document.getElementById('newUserCreate').onclick = function() {
|
||||||
|
const ogText = this.textContent;
|
||||||
|
this.innerHTML = `
|
||||||
|
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Creating...`;
|
||||||
|
const email = document.getElementById('newUserEmail').value;
|
||||||
|
var username = email;
|
||||||
|
if (document.getElementById('newUserName') != null) {
|
||||||
|
username = document.getElementById('newUserName').value;
|
||||||
|
}
|
||||||
|
const password = document.getElementById('newUserPassword').value;
|
||||||
|
if (!validEmail(email) && email != "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const send = {
|
||||||
|
'username': username,
|
||||||
|
'password': password,
|
||||||
|
'email': email
|
||||||
|
}
|
||||||
|
let req = new XMLHttpRequest()
|
||||||
|
req.open("POST", "/newUserAdmin", true);
|
||||||
|
req.responseType = 'json';
|
||||||
|
req.setRequestHeader("Authorization", "Basic " + btoa(window.token + ":"));
|
||||||
|
const button = this;
|
||||||
|
req.onreadystatechange = function() {
|
||||||
|
if (this.readyState == 4) {
|
||||||
|
button.textContent = ogText;
|
||||||
|
if (this.status == 200) {
|
||||||
|
if (button.classList.contains('btn-primary')) {
|
||||||
|
button.classList.remove('btn-primary');
|
||||||
|
}
|
||||||
|
button.classList.add('btn-success');
|
||||||
|
button.textContent = 'Success';
|
||||||
|
setTimeout(function() {
|
||||||
|
if (button.classList.contains('btn-success')) {
|
||||||
|
button.classList.remove('btn-success');
|
||||||
|
}
|
||||||
|
button.classList.add('btn-primary');
|
||||||
|
button.textContent = ogText;
|
||||||
|
newUserModal.hide();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
if (button.classList.contains('btn-primary')) {
|
||||||
|
button.classList.remove('btn-primary');
|
||||||
|
}
|
||||||
|
button.classList.add('btn-danger');
|
||||||
|
if ("error" in req.response) {
|
||||||
|
button.textContent = req.response["error"];
|
||||||
|
} else {
|
||||||
|
button.textContent = 'Failed';
|
||||||
|
}
|
||||||
|
setTimeout(function() {
|
||||||
|
if (button.classList.contains('btn-danger')) {
|
||||||
|
button.classList.remove('btn-danger');
|
||||||
|
}
|
||||||
|
button.classList.add('btn-primary');
|
||||||
|
button.textContent = ogText;
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
req.send(JSON.stringify(send));
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('accountsTabAddUser').onclick = function() {
|
||||||
|
document.getElementById('newUserEmail').value = '';
|
||||||
|
document.getElementById('newUserPassword').value = '';
|
||||||
|
if (document.getElementById('newUserName') != null) {
|
||||||
|
document.getElementById('newUserName').value = '';
|
||||||
|
}
|
||||||
|
newUserModal.show();
|
||||||
|
};
|
||||||
|
@ -135,6 +135,7 @@ var restartModal = createModal('restartModal');
|
|||||||
var refreshModal = createModal('refreshModal');
|
var refreshModal = createModal('refreshModal');
|
||||||
var aboutModal = createModal('aboutModal');
|
var aboutModal = createModal('aboutModal');
|
||||||
var deleteModal = createModal('deleteModal');
|
var deleteModal = createModal('deleteModal');
|
||||||
|
var newUserModal = createModal('newUserModal');
|
||||||
|
|
||||||
// Parsed invite: [<code>, <expires in _>, <1: Empty invite (no delete/link), 0: Actual invite>, <email address>, <remaining uses>, [<used-by>], <date created>, <notify on expiry>, <notify on creation>]
|
// Parsed invite: [<code>, <expires in _>, <1: Empty invite (no delete/link), 0: Actual invite>, <email address>, <remaining uses>, [<used-by>], <date created>, <notify on expiry>, <notify on creation>]
|
||||||
function parseInvite(invite, empty = false) {
|
function parseInvite(invite, empty = false) {
|
||||||
|
@ -207,8 +207,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-light" data-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-light" data-dismiss="modal">Cancel</button>
|
||||||
<button type="button" class="btn btn-secondary" id="applyRestarts" data-dismiss="modal">Apply, Restart later</button>
|
<button type="button" class="btn btn-secondary" id="applyrestarts" data-dismiss="modal">apply, restart later</button>
|
||||||
<button type="button" class="btn btn-primary" id="applyAndRestart" data-dismiss="modal">Apply & Restart</button>
|
<button type="button" class="btn btn-primary" id="applyandrestart" data-dismiss="modal">apply & restart</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -270,6 +270,38 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="modal fade" id="newUserModal" role="dialog" aria-labelledby="Create new user" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Create a user</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="newUserEmail" class="form-label">Email address</label>
|
||||||
|
<input type="email" class="form-control" id="newUserEmail" aria-describedby="Email address">
|
||||||
|
</div>
|
||||||
|
{{ if .username }}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="newUserName" class="form-label">Username</label>
|
||||||
|
<input type="text" class="form-control" id="newUserName" aria-describedby="Username">
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="newUserPassword" class="form-label">Password</label>
|
||||||
|
<input type="password" class="form-control" id="newUserPassword" aria-describedby="Password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-light" data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="newUserCreate">Create</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="pageContainer">
|
<div class="pageContainer">
|
||||||
<h1><a id="invitesTabButton" class="text-button">invites </a><a id="accountsTabButton" class="text-button text-muted">accounts</a></h1>
|
<h1><a id="invitesTabButton" class="text-button">invites </a><a id="accountsTabButton" class="text-button text-muted">accounts</a></h1>
|
||||||
<div class="btn-group" role="group" id="headerButtons">
|
<div class="btn-group" role="group" id="headerButtons">
|
||||||
@ -360,7 +392,7 @@
|
|||||||
<div class="card-header d-flex" style="align-items: center;">
|
<div class="card-header d-flex" style="align-items: center;">
|
||||||
<div>Accounts</div>
|
<div>Accounts</div>
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
<!--<button type="button" class="btn btn-secondary">Add User</button>-->
|
<button type="button" class="btn btn-secondary" id="accountsTabAddUser">Add User</button>
|
||||||
<button type="button" class="btn btn-primary unfocused" id="accountsTabSetDefaults">Set Defaults</button>
|
<button type="button" class="btn btn-primary unfocused" id="accountsTabSetDefaults">Set Defaults</button>
|
||||||
<button type="button" class="btn btn-danger unfocused" id="accountsTabDelete"></button>
|
<button type="button" class="btn btn-danger unfocused" id="accountsTabDelete"></button>
|
||||||
</div>
|
</div>
|
||||||
|
1
main.go
1
main.go
@ -435,6 +435,7 @@ func start(asDaemon, firstCall bool) {
|
|||||||
router.GET("/invite/:invCode", app.InviteProxy)
|
router.GET("/invite/:invCode", app.InviteProxy)
|
||||||
api := router.Group("/", app.webAuth())
|
api := router.Group("/", app.webAuth())
|
||||||
router.POST("/logout", app.Logout)
|
router.POST("/logout", app.Logout)
|
||||||
|
api.POST("/newUserAdmin", app.NewUserAdmin)
|
||||||
api.POST("/generateInvite", app.GenerateInvite)
|
api.POST("/generateInvite", app.GenerateInvite)
|
||||||
api.GET("/getInvites", app.GetInvites)
|
api.GET("/getInvites", app.GetInvites)
|
||||||
api.POST("/setNotify", app.SetNotify)
|
api.POST("/setNotify", app.SetNotify)
|
||||||
|
1
views.go
1
views.go
@ -20,6 +20,7 @@ func (app *appContext) AdminPage(gc *gin.Context) {
|
|||||||
"version": VERSION,
|
"version": VERSION,
|
||||||
"commit": COMMIT,
|
"commit": COMMIT,
|
||||||
"ombiEnabled": ombiEnabled,
|
"ombiEnabled": ombiEnabled,
|
||||||
|
"username": !app.config.Section("email").Key("no_username").MustBool(false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user