diff --git a/store/session.go b/store/session.go index a2a2a82..c94b6ea 100644 --- a/store/session.go +++ b/store/session.go @@ -102,7 +102,7 @@ func sessionUse(ctx context.Context, log mlog.Log, accountName string, sessionTo if !ok { return LoginSession{}, fmt.Errorf("unknown session token") } else if time.Until(ls.Expires) < 0 { - return LoginSession{}, fmt.Errorf("session expired") + return LoginSession{}, fmt.Errorf("session expired (after 24 hours inactivity)") } else if csrfToken != "" && csrfToken != ls.csrfToken { return LoginSession{}, fmt.Errorf("mismatch between csrf and session tokens") } diff --git a/webaccount/account.js b/webaccount/account.js index 25a6ada..be69378 100644 --- a/webaccount/account.js +++ b/webaccount/account.js @@ -885,7 +885,7 @@ const login = async (reason) => { let autosize; let username; let password; - const root = dom.div(style({ position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: '#eee', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: '1', animation: 'fadein .15s ease-in' }), dom.div(reasonElem = reason ? dom.div(style({ marginBottom: '2ex', textAlign: 'center' }), reason) : dom.div(), dom.div(style({ backgroundColor: 'white', borderRadius: '.25em', padding: '1em', boxShadow: '0 0 20px rgba(0, 0, 0, 0.1)', border: '1px solid #ddd', maxWidth: '95vw', overflowX: 'auto', maxHeight: '95vh', overflowY: 'auto', marginBottom: '20vh' }), dom.form(async function submit(e) { + const root = dom.div(style({ position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: '#eee', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: '1', animation: 'fadein .15s ease-in' }), dom.div(style({ display: 'flex', flexDirection: 'column', alignItems: 'center' }), reasonElem = reason ? dom.div(style({ marginBottom: '2ex', textAlign: 'center' }), reason) : dom.div(), dom.div(style({ backgroundColor: 'white', borderRadius: '.25em', padding: '1em', boxShadow: '0 0 20px rgba(0, 0, 0, 0.1)', border: '1px solid #ddd', maxWidth: '95vw', overflowX: 'auto', maxHeight: '95vh', overflowY: 'auto', marginBottom: '20vh' }), dom.form(async function submit(e) { e.preventDefault(); e.stopPropagation(); reasonElem.remove(); diff --git a/webaccount/account.ts b/webaccount/account.ts index e860066..5875066 100644 --- a/webaccount/account.ts +++ b/webaccount/account.ts @@ -19,6 +19,7 @@ const login = async (reason: string) => { const root = dom.div( style({position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: '#eee', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: '1', animation: 'fadein .15s ease-in'}), dom.div( + style({display: 'flex', flexDirection: 'column', alignItems: 'center'}), reasonElem=reason ? dom.div(style({marginBottom: '2ex', textAlign: 'center'}), reason) : dom.div(), dom.div( style({backgroundColor: 'white', borderRadius: '.25em', padding: '1em', boxShadow: '0 0 20px rgba(0, 0, 0, 0.1)', border: '1px solid #ddd', maxWidth: '95vw', overflowX: 'auto', maxHeight: '95vh', overflowY: 'auto', marginBottom: '20vh'}), diff --git a/webadmin/admin.js b/webadmin/admin.js index 3ec8136..5770ed2 100644 --- a/webadmin/admin.js +++ b/webadmin/admin.js @@ -1649,7 +1649,7 @@ const login = async (reason) => { let reasonElem; let fieldset; let password; - const root = dom.div(style({ position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: '#eee', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: '1', animation: 'fadein .15s ease-in' }), dom.div(reasonElem = reason ? dom.div(style({ marginBottom: '2ex', textAlign: 'center' }), reason) : dom.div(), dom.div(style({ backgroundColor: 'white', borderRadius: '.25em', padding: '1em', boxShadow: '0 0 20px rgba(0, 0, 0, 0.1)', border: '1px solid #ddd', maxWidth: '95vw', overflowX: 'auto', maxHeight: '95vh', overflowY: 'auto', marginBottom: '20vh' }), dom.form(async function submit(e) { + const root = dom.div(style({ position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: '#eee', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: '1', animation: 'fadein .15s ease-in' }), dom.div(style({ display: 'flex', flexDirection: 'column', alignItems: 'center' }), reasonElem = reason ? dom.div(style({ marginBottom: '2ex', textAlign: 'center' }), reason) : dom.div(), dom.div(style({ backgroundColor: 'white', borderRadius: '.25em', padding: '1em', boxShadow: '0 0 20px rgba(0, 0, 0, 0.1)', border: '1px solid #ddd', maxWidth: '95vw', overflowX: 'auto', maxHeight: '95vh', overflowY: 'auto', marginBottom: '20vh' }), dom.form(async function submit(e) { e.preventDefault(); e.stopPropagation(); reasonElem.remove(); diff --git a/webadmin/admin.ts b/webadmin/admin.ts index 393939d..c5d504e 100644 --- a/webadmin/admin.ts +++ b/webadmin/admin.ts @@ -16,6 +16,7 @@ const login = async (reason: string) => { const root = dom.div( style({position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: '#eee', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: '1', animation: 'fadein .15s ease-in'}), dom.div( + style({display: 'flex', flexDirection: 'column', alignItems: 'center'}), reasonElem=reason ? dom.div(style({marginBottom: '2ex', textAlign: 'center'}), reason) : dom.div(), dom.div( style({backgroundColor: 'white', borderRadius: '.25em', padding: '1em', boxShadow: '0 0 20px rgba(0, 0, 0, 0.1)', border: '1px solid #ddd', maxWidth: '95vw', overflowX: 'auto', maxHeight: '95vh', overflowY: 'auto', marginBottom: '20vh'}), diff --git a/webauth/admin.go b/webauth/admin.go index 6358ca4..b0387ed 100644 --- a/webauth/admin.go +++ b/webauth/admin.go @@ -105,9 +105,9 @@ func (a *adminSessionAuth) use(ctx context.Context, log mlog.Log, accountName st s, ok := a.sessions[sessionToken] if !ok { - return "", fmt.Errorf("unknown session") + return "", fmt.Errorf("unknown session (due to server restart or 10 new admin sessions)") } else if time.Until(s.expires) < 0 { - return "", fmt.Errorf("session expired") + return "", fmt.Errorf("session expired (after 12 hours inactivity)") } else if csrfToken != "" && csrfToken != s.csrfToken { return "", fmt.Errorf("mismatch between csrf and session tokens") } diff --git a/webmail/webmail.js b/webmail/webmail.js index d6f37c5..34d66df 100644 --- a/webmail/webmail.js +++ b/webmail/webmail.js @@ -1631,7 +1631,7 @@ const login = async (reason) => { let autosize; let username; let password; - const root = dom.div(css('loginOverlay', { position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: styles.overlayOpaqueBackgroundColor, display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: zindexes.login, animation: 'fadein .15s ease-in' }), dom.div(reasonElem = reason ? dom.div(css('sessionError', { marginBottom: '2ex', textAlign: 'center' }), reason) : dom.div(), dom.div(css('loginPopup', { + const root = dom.div(css('loginOverlay', { position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: styles.overlayOpaqueBackgroundColor, display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: zindexes.login, animation: 'fadein .15s ease-in' }), dom.div(style({ display: 'flex', flexDirection: 'column', alignItems: 'center' }), reasonElem = reason ? dom.div(css('sessionError', { marginBottom: '2ex', textAlign: 'center' }), reason) : dom.div(), dom.div(css('loginPopup', { backgroundColor: styles.popupBackgroundColor, boxShadow: styles.boxShadow, border: '1px solid', diff --git a/webmail/webmail.ts b/webmail/webmail.ts index 5c2a24b..51d6319 100644 --- a/webmail/webmail.ts +++ b/webmail/webmail.ts @@ -271,6 +271,7 @@ const login = async (reason: string) => { const root = dom.div( css('loginOverlay', {position: 'absolute', top: 0, right: 0, bottom: 0, left: 0, backgroundColor: styles.overlayOpaqueBackgroundColor, display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: zindexes.login, animation: 'fadein .15s ease-in'}), dom.div( + style({display: 'flex', flexDirection: 'column', alignItems: 'center'}), reasonElem=reason ? dom.div(css('sessionError', {marginBottom: '2ex', textAlign: 'center'}), reason) : dom.div(), dom.div( css('loginPopup', {