Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b1d329f7c |
@@ -38,7 +38,6 @@ val membyGatewayUrl: String = (project.findProperty("memby.gatewayUrl") as Strin
|
|||||||
val membyDiagnosticLogLevel: String = (project.findProperty("memby.diagnosticLogLevel") as String?)
|
val membyDiagnosticLogLevel: String = (project.findProperty("memby.diagnosticLogLevel") as String?)
|
||||||
?.trim()?.uppercase()?.takeIf { it in setOf("INFO", "DEBUG", "TRACE") } ?: "INFO"
|
?.trim()?.uppercase()?.takeIf { it in setOf("INFO", "DEBUG", "TRACE") } ?: "INFO"
|
||||||
|
|
||||||
|
|
||||||
val defaultVersionName = "0.3.40"
|
val defaultVersionName = "0.3.40"
|
||||||
val membyVersionName: String =
|
val membyVersionName: String =
|
||||||
(project.findProperty("memby.versionName") as String?)
|
(project.findProperty("memby.versionName") as String?)
|
||||||
|
|||||||
@@ -180,6 +180,37 @@ func TestAdminSignInAsksEmbyWhenTheAuthResponseCarriesNoPolicy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The user switcher names whoever is signed in, so an admin session must carry the
|
||||||
|
// verified Emby account name. A fresh sign-in does; a session predating the identity in
|
||||||
|
// the cookie is still valid but anonymous, and the console handler prompts those to sign
|
||||||
|
// in again rather than falling back to "Administrator" for ever.
|
||||||
|
func TestAdminSessionCarriesTheVerifiedName(t *testing.T) {
|
||||||
|
s := embyAccessLevel(t, `{"IsAdministrator":true}`, "")
|
||||||
|
|
||||||
|
cookie := sessionCookie(signIn(s, "/admin/"))
|
||||||
|
if cookie == nil {
|
||||||
|
t.Fatal("admin sign-in issued no session")
|
||||||
|
}
|
||||||
|
named := httptest.NewRequest(http.MethodGet, "/admin/", nil)
|
||||||
|
named.AddCookie(cookie)
|
||||||
|
if !s.adminSessionNamed(named) {
|
||||||
|
t.Fatal("a fresh admin session is missing the verified name")
|
||||||
|
}
|
||||||
|
|
||||||
|
anon, err := s.newBrowserSessionFor(adminSessionPurpose, adminSessionTTL, "")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("anonymous session: %v", err)
|
||||||
|
}
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/admin/", nil)
|
||||||
|
req.AddCookie(&http.Cookie{Name: installerCookieName, Value: anon})
|
||||||
|
if !s.validAdminSession(req) {
|
||||||
|
t.Fatal("an anonymous admin session should still be valid")
|
||||||
|
}
|
||||||
|
if s.adminSessionNamed(req) {
|
||||||
|
t.Fatal("an anonymous admin session should not report a name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// And an Emby that will not answer either way must not be guessed at in the permissive
|
// And an Emby that will not answer either way must not be guessed at in the permissive
|
||||||
// direction: no answer means no session.
|
// direction: no answer means no session.
|
||||||
func TestAdminSignInIsRefusedWhenTheAccessLevelCannotBeRead(t *testing.T) {
|
func TestAdminSignInIsRefusedWhenTheAccessLevelCannotBeRead(t *testing.T) {
|
||||||
|
|||||||
@@ -109,6 +109,14 @@ func (s *Server) handleAdminConsole(w http.ResponseWriter, r *http.Request) {
|
|||||||
s.renderAccessLogin(w, r, "", http.StatusOK, r.URL.Path)
|
s.renderAccessLogin(w, r, "", http.StatusOK, r.URL.Path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// A valid but anonymous session (minted before the cookie carried the operator's
|
||||||
|
// name) leaves the console unable to say who is signed in. Prompt for the shell only,
|
||||||
|
// so a fresh sign-in fills the name in without breaking asset requests mid-session.
|
||||||
|
if isAdminDocumentRequest(r) && !s.adminSessionNamed(r) {
|
||||||
|
s.renderAccessLogin(w, r, "Please sign in again to continue.",
|
||||||
|
http.StatusOK, r.URL.Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
// Opening a page is somebody at the keyboard, so it starts the clock again.
|
// Opening a page is somebody at the keyboard, so it starts the clock again.
|
||||||
s.renewAdminSession(w, r)
|
s.renewAdminSession(w, r)
|
||||||
s.setAdminTokenCookie(w, r)
|
s.setAdminTokenCookie(w, r)
|
||||||
|
|||||||
@@ -164,6 +164,17 @@ func (s *Server) validAdminSession(r *http.Request) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adminSessionNamed reports whether the request's admin session carries the verified Emby
|
||||||
|
// account name. Every session minted since the identity was added to the cookie has one;
|
||||||
|
// a session predating it is valid but anonymous, which is what makes the console's user
|
||||||
|
// switcher fall back to "Administrator" instead of showing who is signed in. The console
|
||||||
|
// document handler treats an anonymous session as needing a fresh sign-in so the name is
|
||||||
|
// picked up — a one-time prompt, since renewal preserves whatever the cookie already held.
|
||||||
|
func (s *Server) adminSessionNamed(r *http.Request) bool {
|
||||||
|
_, username, ok := s.browserSession(r, adminSessionPurpose)
|
||||||
|
return ok && username != ""
|
||||||
|
}
|
||||||
|
|
||||||
// renewAdminSession slides a valid session's expiry forward. The TTL was absolute and
|
// renewAdminSession slides a valid session's expiry forward. The TTL was absolute and
|
||||||
// nothing extended it, so an operator working the admin console was signed out from under
|
// nothing extended it, so an operator working the admin console was signed out from under
|
||||||
// themselves and the page's poll became a permanent "invalid admin
|
// themselves and the page's poll became a permanent "invalid admin
|
||||||
|
|||||||
Reference in New Issue
Block a user