diff --git a/CHANGELOG.md b/CHANGELOG.md index a2ec307acb33b1af7a7943cf810bd7d31b5b8a2e..c216a5e1d8201c00c6d2495bad0bfa246f0d53e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,9 +14,19 @@ ## mytoken 0.7.0 +### Features + +- Webinterface has option to show event history for other mytokens in mytoken list. + ### Enhancements - Improved responsiveness of webinterface +- Expired mytokens are now greyed-out in webinterface mytoken list +- The database auto-cleanup now only removes mytokens expired more than a month ago. + - This allows expired tokens to be shown in a mytoken list for extended periods. + - This also allows to obtain history for expired tokens (by using a mytoken with the `manage_mytokens:list` + capability) for a longer time. + - Mytokens are still directly deleted when revoked. ### API diff --git a/go.mod b/go.mod index 314dfa14fda356ca8edcbd2dc89e2065a4f193bd..44d84c1d910147eee5ec08780ace4fb586e78b6a 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/jinzhu/copier v0.3.5 github.com/jmoiron/sqlx v1.3.5 github.com/lestrrat-go/jwx v1.2.25 - github.com/oidc-mytoken/api v0.9.2-0.20221125114557-91c7bae719ca + github.com/oidc-mytoken/api v0.9.2-0.20221205154634-0c914eb8569d github.com/oidc-mytoken/lib v0.6.2-0.20221125141521-dae7f2a63fc2 github.com/oidc-mytoken/utils v0.1.0 github.com/patrickmn/go-cache v2.1.0+incompatible diff --git a/go.sum b/go.sum index 65e0ae8ca7d5ffe212980bf182ba0dd5d2e4ac11..aca021745b4f2fc35152f8a3c8491815a47ba877 100644 --- a/go.sum +++ b/go.sum @@ -373,6 +373,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/oidc-mytoken/api v0.9.1/go.mod h1:DBIlUbaIgGlf607VZx8zFC97VR3WNN0kaMVO1AqyTdE= github.com/oidc-mytoken/api v0.9.2-0.20221125114557-91c7bae719ca h1:Az8gcUKX98Yh48RSxMHEioy0KdJaOvJVCpTtW+tcLR8= github.com/oidc-mytoken/api v0.9.2-0.20221125114557-91c7bae719ca/go.mod h1:DBIlUbaIgGlf607VZx8zFC97VR3WNN0kaMVO1AqyTdE= +github.com/oidc-mytoken/api v0.9.2-0.20221205154634-0c914eb8569d h1:cAP+SXYJMkiwJhWpj4YCjL5OuJ8+OMaxRW8eDdBh1Cg= +github.com/oidc-mytoken/api v0.9.2-0.20221205154634-0c914eb8569d/go.mod h1:DBIlUbaIgGlf607VZx8zFC97VR3WNN0kaMVO1AqyTdE= github.com/oidc-mytoken/lib v0.6.2-0.20221125141521-dae7f2a63fc2 h1:ygQMfCtOGnZxsW7cAhBZCSfGgg3qcfvPVkc2Wq+0L4A= github.com/oidc-mytoken/lib v0.6.2-0.20221125141521-dae7f2a63fc2/go.mod h1:U0mC1zWdWKYPekoNTYSQZB5SHFk4fPz+JhfPgWs4TTs= github.com/oidc-mytoken/utils v0.1.0 h1:Ia60CYjVzs4X35twdAB1NTXDyYjxe/IWDI/MkcvQHnc= diff --git a/internal/db/dbmigrate/scripts/v0.7.0.pre.sql b/internal/db/dbmigrate/scripts/v0.7.0.pre.sql index df3d342c40edb379151daf26dadbee3b9c93d801..633e1c61a5c0bc63688583b9f689dfe0d740b2e0 100644 --- a/internal/db/dbmigrate/scripts/v0.7.0.pre.sql +++ b/internal/db/dbmigrate/scripts/v0.7.0.pre.sql @@ -37,5 +37,50 @@ BEGIN DROP TABLE effected_MTIDs; END;; +CREATE OR REPLACE PROCEDURE Cleanup_MTokens() +BEGIN + DELETE FROM MTokens WHERE DATE_ADD(expires_at, INTERVAL 1 MONTH) < CURRENT_TIMESTAMP(); +END;; + +CREATE OR REPLACE PROCEDURE Cleanup_ProxyTokens() +BEGIN + DELETE + FROM ProxyTokens + WHERE id IN (SELECT id + FROM TransferCodesAttributes + WHERE DATE_ADD(expires_at, INTERVAL 1 MONTH) < CURRENT_TIMESTAMP()); +END;; + +CREATE OR REPLACE PROCEDURE MTokens_GetForUser(IN UID BIGINT UNSIGNED) +BEGIN + SELECT id, parent_id, id AS mom_id, name, created, expires_at, ip_created AS ip + FROM MTokens + WHERE user_id = UID + ORDER BY created; +END; + +CREATE OR REPLACE PROCEDURE MTokens_GetSubtokens(IN MTID VARCHAR(128)) +BEGIN + CREATE TEMPORARY TABLE IF NOT EXISTS effected_MTIDs (id VARCHAR(128)); + TRUNCATE effected_MTIDs; + INSERT INTO effected_MTIDs + WITH RECURSIVE childs AS (SELECT id, parent_id + FROM MTokens + WHERE id = MTID + UNION ALL + SELECT mt.id, mt.parent_id + FROM MTokens mt + INNER JOIN childs c + WHERE mt.parent_id = c.id) + SELECT id + FROM childs; + SELECT m.id, m.parent_id, m.id AS mom_id, m.name, m.created, m.expires_at, m.ip_created AS ip + FROM MTokens m + WHERE m.id IN + (SELECT id + FROM effected_MTIDs); + DROP TABLE effected_MTIDs; +END; + DELIMITER ; diff --git a/internal/db/dbrepo/mytokenrepo/tree/tree.go b/internal/db/dbrepo/mytokenrepo/tree/tree.go index c2e5c323255546f484608a75545a86b44e1e65e7..de3ce2790937821eec25ca31fc4ecaf477a92eeb 100644 --- a/internal/db/dbrepo/mytokenrepo/tree/tree.go +++ b/internal/db/dbrepo/mytokenrepo/tree/tree.go @@ -20,6 +20,7 @@ type MytokenEntry struct { ParentID mtid.MTID `db:"parent_id" json:"-"` Name db.NullString `json:"name,omitempty"` CreatedAt unixtime.UnixTime `db:"created" json:"created"` + ExpiresAt unixtime.UnixTime `db:"expires_at" json:"expires_at,omitempty"` MOMID string `db:"mom_id" json:"mom_id"` } diff --git a/internal/server/web/static/js/tokeninfo.js b/internal/server/web/static/js/tokeninfo.js index cc64400874677d772b026e6d71ce226573d8dc0c..eb8250e2f42edc1303a782cf66fb001c1c299035 100644 --- a/internal/server/web/static/js/tokeninfo.js +++ b/internal/server/web/static/js/tokeninfo.js @@ -129,7 +129,9 @@ function _tokenTreeToHTML(tree, deleteClass, depth, parentID = 0) { let name = token['name'] || 'unnamed token'; let nameClass = name === 'unnamed token' ? ' text-muted' : ''; let thisID = `token-tree-el-${tokenTreeIDCounter++}` - let time = formatTime(token['created']); + let created = formatTime(token['created']); + let expires_at = token['expires_at'] || 0; + let expires = expires_at === 0 ? `<span class="text-muted">Does not expire</span>` : formatTime(expires_at); let tableEntries = ""; let children = tree['children']; let hasChildren = false; @@ -141,7 +143,11 @@ function _tokenTreeToHTML(tree, deleteClass, depth, parentID = 0) { } let historyBtn = `<button id="history-${token['mom_id']}" class="btn ml-2" type="button" onclick="showHistoryForID.call(this)" ${loggedIn ? "" : "disabled"} data-toggle="tooltip" data-placement="right" title="${loggedIn ? 'Event History' : 'Sign in to show event history.'}"><i class="fas fa-history"></i></button>`; let deleteBtn = `<button id="revoke-${token['mom_id']}" class="btn ${deleteClass}" type="button" onclick="startRevocateID.call(this)" ${loggedIn ? "" : "disabled"} data-toggle="tooltip" data-placement="right" title="${loggedIn ? 'Revoke Token' : 'Sign in to revoke token.'}"><i class="fas fa-trash"></i></button>`; - tableEntries = `<tr id="${thisID}" parent-id="${parentID}" class="${depth > 0 ? 'd-none' : ''}"><td class="${hasChildren ? 'token-fold' : ''}${nameClass}"><span style="margin-right: ${1.5 * depth}rem;"></span><i class="mr-2 fas fa-caret-right${hasChildren ? "" : " d-none"}"></i>${name}</td><td>${time}</td><td>${token['ip']}</td><td>${historyBtn}${deleteBtn}</td></tr>` + tableEntries; + let tr_class = depth > 0 ? 'd-none' : ''; + if (expires_at !== 0 && new Date(expires_at * 1000) < new Date()) { + tr_class += " text-muted"; + } + tableEntries = `<tr id="${thisID}" parent-id="${parentID}" class="${tr_class}"><td class="${hasChildren ? 'token-fold' : ''}${nameClass}"><span style="margin-right: ${1.5 * depth}rem;"></span><i class="mr-2 fas fa-caret-right${hasChildren ? "" : " d-none"}"></i>${name}</td><td>${created}</td><td>${token['ip']}</td><td>${expires}</td><td>${historyBtn}${deleteBtn}</td></tr>` + tableEntries; return tableEntries } @@ -155,9 +161,10 @@ function tokenlistToHTML(tokenTrees, deleteClass) { } return '<table class="table table-hover table-grey">' + '<thead><tr>' + - '<th style="min-width: 50%;">Token Name</th>' + + '<th style="min-width: 40%;">Token Name</th>' + '<th>Created</th>' + '<th>Created from IP</th>' + + '<th>Expires</th>' + '<th></th>' + '</tr></thead>' + '<tbody>' +