|
@@ -0,0 +1,124 @@
|
|
|
|
|
+import minimist from 'minimist'
|
|
|
|
|
+import { db, ObjectId } from '../../app/src/infrastructure/mongodb.mjs'
|
|
|
|
|
+import { scriptRunner } from '../lib/ScriptRunner.mjs'
|
|
|
|
|
+
|
|
|
|
|
+// Test helper: move a personal access token's accessTokenExpiresAt EARLIER, to
|
|
|
|
|
+// simulate an expiring-soon or already-expired token when manually testing the
|
|
|
|
|
+// expiry-notification flow (notify_expiring_tokens.mjs / git-bridge messaging).
|
|
|
|
|
+//
|
|
|
|
|
+// This script can only ever back-date a token: it refuses to set an expiry that
|
|
|
|
|
+// is later than the token's current one. Moving an expiry forward would extend
|
|
|
|
|
+// the life of a token that should be dead, so that direction is disallowed.
|
|
|
|
|
+//
|
|
|
|
|
+// Pass --dry-run to report what would change without writing.
|
|
|
|
|
+
|
|
|
|
|
+async function main() {
|
|
|
|
|
+ const opts = parseArgs()
|
|
|
|
|
+
|
|
|
|
|
+ const token = await db.oauthAccessTokens.findOne({
|
|
|
|
|
+ _id: new ObjectId(opts.tokenId),
|
|
|
|
|
+ })
|
|
|
|
|
+ if (token == null) {
|
|
|
|
|
+ console.error(`No oauthAccessToken found with _id ${opts.tokenId}`)
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const currentExpiry = token.accessTokenExpiresAt
|
|
|
|
|
+ if (!(currentExpiry instanceof Date) || isNaN(currentExpiry.getTime())) {
|
|
|
|
|
+ console.error(
|
|
|
|
|
+ `Token ${opts.tokenId} has no valid accessTokenExpiresAt ` +
|
|
|
|
|
+ `(found: ${JSON.stringify(currentExpiry)}). ` +
|
|
|
|
|
+ 'This script only operates on tokens with an expiry, such as PATs.'
|
|
|
|
|
+ )
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (opts.expiry >= currentExpiry) {
|
|
|
|
|
+ console.error(
|
|
|
|
|
+ `Refusing to move expiry forward: requested ${opts.expiry.toISOString()} ` +
|
|
|
|
|
+ `is not earlier than current ${currentExpiry.toISOString()}. ` +
|
|
|
|
|
+ 'This script only back-dates token expiry.'
|
|
|
|
|
+ )
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (opts.dryRun) {
|
|
|
|
|
+ console.warn(
|
|
|
|
|
+ `[dry run] would back-date token ${opts.tokenId} expiry from ` +
|
|
|
|
|
+ `${currentExpiry.toISOString()} to ${opts.expiry.toISOString()}`
|
|
|
|
|
+ )
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ await db.oauthAccessTokens.updateOne(
|
|
|
|
|
+ { _id: token._id },
|
|
|
|
|
+ { $set: { accessTokenExpiresAt: opts.expiry } }
|
|
|
|
|
+ )
|
|
|
|
|
+ console.warn(
|
|
|
|
|
+ `Back-dated token ${opts.tokenId} expiry from ` +
|
|
|
|
|
+ `${currentExpiry.toISOString()} to ${opts.expiry.toISOString()}`
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function parseArgs() {
|
|
|
|
|
+ const args = minimist(process.argv.slice(2), {
|
|
|
|
|
+ boolean: ['help', 'dry-run'],
|
|
|
|
|
+ })
|
|
|
|
|
+ if (args.help) {
|
|
|
|
|
+ usage()
|
|
|
|
|
+ process.exit(0)
|
|
|
|
|
+ }
|
|
|
|
|
+ if (args._.length !== 0) {
|
|
|
|
|
+ usage()
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const tokenId = args['token-id']
|
|
|
|
|
+ if (tokenId == null) {
|
|
|
|
|
+ console.error('Missing --token-id option')
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!ObjectId.isValid(tokenId)) {
|
|
|
|
|
+ console.error(`Invalid --token-id: ${tokenId}`)
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (args['expiry-date'] == null) {
|
|
|
|
|
+ console.error('Missing --expiry-date option')
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+ const expiry = new Date(args['expiry-date'])
|
|
|
|
|
+ if (isNaN(expiry.getTime())) {
|
|
|
|
|
+ console.error(`Invalid --expiry-date: ${args['expiry-date']}`)
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return {
|
|
|
|
|
+ tokenId,
|
|
|
|
|
+ expiry,
|
|
|
|
|
+ dryRun: args['dry-run'],
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function usage() {
|
|
|
|
|
+ console.error(`Usage: backdate_token_expiry.mjs [OPTS...]
|
|
|
|
|
+
|
|
|
|
|
+Moves a personal access token's expiry EARLIER, to simulate an expiring or
|
|
|
|
|
+expired token when testing the expiry-notification flow. Only ever back-dates;
|
|
|
|
|
+refuses to move an expiry forward.
|
|
|
|
|
+
|
|
|
|
|
+Options:
|
|
|
|
|
+ --token-id _id of the oauthAccessToken to back-date
|
|
|
|
|
+ --expiry-date New expiry, earlier than the current one (e.g. 2026-06-01T00:00:00Z)
|
|
|
|
|
+ --dry-run Report the change without writing
|
|
|
|
|
+ --help Show this message
|
|
|
|
|
+`)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+try {
|
|
|
|
|
+ await scriptRunner(main)
|
|
|
|
|
+ process.exit(0)
|
|
|
|
|
+} catch (error) {
|
|
|
|
|
+ console.error(error)
|
|
|
|
|
+ process.exit(1)
|
|
|
|
|
+}
|