first commit

This commit is contained in:
2025-04-24 13:11:28 +08:00
commit ff9c54d5e4
5960 changed files with 834111 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
import {
db,
READ_PREFERENCE_SECONDARY,
} from '../../app/src/infrastructure/mongodb.js'
import { hashSecret } from '../../modules/oauth2-server/app/src/SecretsHelper.js'
async function main() {
console.log('Hashing client secrets...')
await hashSecrets(db.oauthApplications, 'clientSecret')
console.log('Hashing access tokens...')
await hashSecrets(db.oauthAccessTokens, 'accessToken')
console.log('Hashing refresh tokens...')
await hashSecrets(db.oauthAccessTokens, 'refreshToken')
console.log('Hashing authorization codes...')
await hashSecrets(db.oauthAuthorizationCodes, 'authorizationCode')
}
async function hashSecrets(collection, field) {
const cursor = collection.find(
{
[field]: /^(?!v1\.)/,
},
{
projection: { _id: 1, [field]: 1 },
readPreference: READ_PREFERENCE_SECONDARY,
}
)
let hashedCount = 0
for await (const doc of cursor) {
const hash = hashSecret(doc[field])
await collection.updateOne({ _id: doc._id }, { $set: { [field]: hash } })
hashedCount++
}
console.log(`${hashedCount} secrets hashed`)
}
try {
await main()
process.exit(0)
} catch (error) {
console.error(error)
process.exit(1)
}

View File

@@ -0,0 +1,96 @@
import minimist from 'minimist'
import { db } from '../../app/src/infrastructure/mongodb.js'
import { hashSecret } from '../../modules/oauth2-server/app/src/SecretsHelper.js'
async function main() {
const opts = parseArgs()
if (opts.accessToken == null) {
console.error('Missing --token option')
process.exit(1)
}
if (opts.refreshToken == null) {
console.error('Missing --refresh-token option')
process.exit(1)
}
if (opts.oauthApplication_id == null) {
console.error('Missing --application-id option')
process.exit(1)
}
if (opts.user_id == null) {
console.error('Missing --user-id option')
process.exit(1)
}
if (opts.scope == null) {
console.error('Missing --scope option')
process.exit(1)
}
if (opts.accessTokenExpiresAt == null) {
console.error('Missing --expiry-date option')
process.exit(1)
}
await insertToken(opts)
}
async function insertToken(opts) {
const token = {
...opts,
accessToken: hashSecret(opts.accessToken),
refreshToken: hashSecret(opts.refreshToken),
accessTokenExpiresAt: new Date(opts.accessTokenExpiresAt),
createdAt: new Date(),
}
await db.oauthAccessTokens.insertOne(token)
}
function parseArgs() {
const args = minimist(process.argv.slice(2), {
boolean: ['help'],
})
if (args.help) {
usage()
process.exit(0)
}
if (args._.length !== 0) {
usage()
process.exit(1)
}
return {
accessToken: args.token,
oauthApplication_id: args['application-id'],
refreshToken: args['refresh-token'],
user_id: args['user-id'],
scope: args.scope,
accessTokenExpiresAt: args['expiry-date'],
}
}
function usage() {
console.error(`Usage: create_token.js [OPTS...]
Creates an OAuth access token
Options:
--application-id ID for the OAuth application
--user-id ID of the user this token belongs to
--token Access token
--refresh-token Refresh token
--scope Accepted scope
--expiry-date Token expiry date
`)
}
try {
await main()
process.exit(0)
} catch (error) {
console.error(error)
process.exit(1)
}

View File

@@ -0,0 +1,129 @@
import minimist from 'minimist'
import mongodb from 'mongodb-legacy'
import { db } from '../../app/src/infrastructure/mongodb.js'
import { hashSecret } from '../../modules/oauth2-server/app/src/SecretsHelper.js'
const { ObjectId } = mongodb
async function main() {
const opts = parseArgs()
const application = await getApplication(opts.id)
if (application == null) {
console.log(
`Application ${opts.id} is not registered. Creating a new configuration.`
)
if (opts.name == null) {
console.error('Missing --name option')
process.exit(1)
}
if (opts.secret == null) {
console.error('Missing --secret option')
process.exit(1)
}
} else {
console.log(`Updating configuration for client: ${application.name}`)
if (opts.mongoId != null) {
console.error('Cannot change Mongo ID for an existing client')
process.exit(1)
}
}
await upsertApplication(opts)
}
async function getApplication(clientId) {
return await db.oauthApplications.findOne({ id: clientId })
}
async function upsertApplication(opts) {
const key = { id: opts.id }
const defaults = {}
const updates = {}
if (opts.name != null) {
updates.name = opts.name
}
if (opts.secret != null) {
updates.clientSecret = hashSecret(opts.secret)
}
if (opts.grants != null) {
updates.grants = opts.grants
} else {
defaults.grants = []
}
if (opts.scopes != null) {
updates.scopes = opts.scopes
} else {
defaults.scopes = []
}
if (opts.redirectUris != null) {
updates.redirectUris = opts.redirectUris
} else {
defaults.redirectUris = []
}
if (opts.mongoId != null) {
defaults._id = new ObjectId(opts.mongoId)
}
await db.oauthApplications.updateOne(
key,
{
$setOnInsert: { ...key, ...defaults },
$set: updates,
},
{ upsert: true }
)
}
function parseArgs() {
const args = minimist(process.argv.slice(2), {
boolean: ['help'],
})
if (args.help) {
usage()
process.exit(0)
}
if (args._.length !== 1) {
usage()
process.exit(1)
}
return {
id: args._[0],
mongoId: args['mongo-id'],
name: args.name,
secret: args.secret,
scopes: toArray(args.scope),
grants: toArray(args.grant),
redirectUris: toArray(args['redirect-uri']),
}
}
function usage() {
console.error(`Usage: register_client.js [OPTS...] CLIENT_ID
Creates or updates an OAuth client configuration
Options:
--name Descriptive name for the OAuth client (required for creation)
--secret Client secret (required for creation)
--scope Accepted scope (can be given more than once)
--grant Accepted grant type (can be given more than once)
--redirect-uri Accepted redirect URI (can be given more than once)
--mongo-id Mongo ID to use if the configuration is created (optional)
`)
}
function toArray(value) {
if (value != null && !Array.isArray(value)) {
return [value]
} else {
return value
}
}
try {
await main()
process.exit(0)
} catch (error) {
console.error(error)
process.exit(1)
}

View File

@@ -0,0 +1,121 @@
import minimist from 'minimist'
import {
db,
READ_PREFERENCE_SECONDARY,
} from '../../app/src/infrastructure/mongodb.js'
async function main() {
const opts = parseArgs()
const application = await getApplication(opts.clientId)
if (application == null) {
console.error(`Client configuration not found: ${opts.clientId}`)
process.exit(1)
}
if (opts.commit) {
console.log(
`Preparing to remove OAuth client configuration: ${application.name}.`
)
const deletedAccessTokens = await deleteAccessTokens(application._id)
console.log(`Deleted ${deletedAccessTokens} access tokens`)
const deletedAuthorizationCodes = await deleteAuthorizationCodes(
application._id
)
console.log(`Deleted ${deletedAuthorizationCodes} authorization codes`)
await deleteApplication(application._id)
console.log('Deleted OAuth client configuration')
} else {
console.log(
`Preparing to remove OAuth client configuration (dry run): ${application.name}.`
)
const accessTokenCount = await countAccessTokens(application._id)
const authorizationCodeCount = await countAuthorizationCodes(
application._id
)
console.log(
`This would delete ${accessTokenCount} access tokens and ${authorizationCodeCount} authorization codes.`
)
console.log('This was a dry run. Rerun with --commit to proceed.')
}
}
async function getApplication(clientId) {
return await db.oauthApplications.findOne({ id: clientId })
}
async function countAccessTokens(applicationId) {
return await db.oauthAccessTokens.count(
{
oauthApplication_id: applicationId,
},
{ readPreference: READ_PREFERENCE_SECONDARY }
)
}
async function countAuthorizationCodes(applicationId) {
return await db.oauthAuthorizationCodes.count(
{
oauthApplication_id: applicationId,
},
{ readPreference: READ_PREFERENCE_SECONDARY }
)
}
async function deleteAccessTokens(applicationId) {
const res = await db.oauthAccessTokens.deleteMany({
oauthApplication_id: applicationId,
})
return res.deletedCount
}
async function deleteAuthorizationCodes(applicationId) {
const res = await db.oauthAuthorizationCodes.deleteMany({
oauthApplication_id: applicationId,
})
return res.deletedCount
}
async function deleteApplication(applicationId) {
await db.oauthApplications.deleteOne({ _id: applicationId })
}
function parseArgs() {
const args = minimist(process.argv.slice(2), {
boolean: ['help', 'commit'],
})
if (args.help) {
usage()
process.exit(0)
}
if (args._.length !== 1) {
usage()
process.exit(1)
}
return {
clientId: args._[0],
commit: args.commit,
}
}
function usage() {
console.error(`Usage: remove_client.js [OPTS...] CLIENT_ID
Removes an OAuth client configuration and all associated tokens and
authorization codes
Options:
--commit Really delete the OAuth application (will do a dry run by default)
`)
}
try {
await main()
process.exit(0)
} catch (error) {
console.error(error)
process.exit(1)
}