feat(platform): gate kick, ban, and bot install tokens behind step-up PIN
Wire pearcord-step-up into bootstrap and view snapshot (stepUpPinSet, stepUpUnlocked). Add setStepUpPin, verifyStepUpPin, clearStepUpPin, and _assertStepUp before moderation and bot-admin APIs. Depends on pearcord-step-up. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -20,6 +20,7 @@ const { PearcordEmojiRegistry } = require('pearcord-emoji')
|
|||||||
const { BotEventFanout, BOT_EVENTS } = require('pearcord-bot-events')
|
const { BotEventFanout, BOT_EVENTS } = require('pearcord-bot-events')
|
||||||
const { INTENTS } = require('pearcord-bot-sdk')
|
const { INTENTS } = require('pearcord-bot-sdk')
|
||||||
const { BotRateLimits } = require('pearcord-bot-limits')
|
const { BotRateLimits } = require('pearcord-bot-limits')
|
||||||
|
const { PearcordStepUp } = require('pearcord-step-up')
|
||||||
const {
|
const {
|
||||||
createInstallToken,
|
createInstallToken,
|
||||||
verifyInstallToken,
|
verifyInstallToken,
|
||||||
@@ -192,6 +193,11 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
})
|
})
|
||||||
await this.userSettings.ready()
|
await this.userSettings.ready()
|
||||||
this.userSettings.on('prefs', () => this.emit('user-prefs'))
|
this.userSettings.on('prefs', () => this.emit('user-prefs'))
|
||||||
|
this.stepUp = new PearcordStepUp({
|
||||||
|
storagePath: this.storagePath,
|
||||||
|
userId: user.id
|
||||||
|
})
|
||||||
|
await this.stepUp.ready()
|
||||||
this.guilds = await this.listGuilds()
|
this.guilds = await this.listGuilds()
|
||||||
await this._joinDiscoveryMesh()
|
await this._joinDiscoveryMesh()
|
||||||
await this._joinContactsMesh()
|
await this._joinContactsMesh()
|
||||||
@@ -1629,6 +1635,51 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
return bot
|
return bot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _ensureStepUp () {
|
||||||
|
const user = this.identity?.user
|
||||||
|
if (!user) throw new Error('register first')
|
||||||
|
if (!this.stepUp) {
|
||||||
|
this.stepUp = new PearcordStepUp({
|
||||||
|
storagePath: this.storagePath,
|
||||||
|
userId: user.id
|
||||||
|
})
|
||||||
|
await this.stepUp.ready()
|
||||||
|
} else {
|
||||||
|
this.stepUp.setUserId(user.id)
|
||||||
|
}
|
||||||
|
return this.stepUp
|
||||||
|
}
|
||||||
|
|
||||||
|
async _assertStepUp () {
|
||||||
|
const stepUp = await this._ensureStepUp()
|
||||||
|
await stepUp.assertVerified()
|
||||||
|
}
|
||||||
|
|
||||||
|
async setStepUpPin (pin) {
|
||||||
|
const stepUp = await this._ensureStepUp()
|
||||||
|
return stepUp.setPin(pin)
|
||||||
|
}
|
||||||
|
|
||||||
|
async verifyStepUpPin (pin) {
|
||||||
|
const stepUp = await this._ensureStepUp()
|
||||||
|
const ok = await stepUp.verifyPin(pin)
|
||||||
|
if (!ok) throw new Error('incorrect PIN')
|
||||||
|
return { unlocked: true, until: stepUp.sessionExpiresAt() }
|
||||||
|
}
|
||||||
|
|
||||||
|
async clearStepUpPin () {
|
||||||
|
const stepUp = await this._ensureStepUp()
|
||||||
|
return stepUp.clearPin()
|
||||||
|
}
|
||||||
|
|
||||||
|
async getStepUpStatus () {
|
||||||
|
const stepUp = await this._ensureStepUp()
|
||||||
|
return {
|
||||||
|
pinSet: await stepUp.hasPin(),
|
||||||
|
unlocked: stepUp.isSessionActive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async createBotInstallToken ({
|
async createBotInstallToken ({
|
||||||
name,
|
name,
|
||||||
intents = INTENTS.GUILD_MESSAGES | INTENTS.MESSAGE_CONTENT,
|
intents = INTENTS.GUILD_MESSAGES | INTENTS.MESSAGE_CONTENT,
|
||||||
@@ -1640,6 +1691,7 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
if (!this.guild?.guild) throw new Error('no guild')
|
if (!this.guild?.guild) throw new Error('no guild')
|
||||||
const user = this.identity.user
|
const user = this.identity.user
|
||||||
if (!user) throw new Error('register first')
|
if (!user) throw new Error('register first')
|
||||||
|
await this._assertStepUp()
|
||||||
const roles = await this._memberRoles()
|
const roles = await this._memberRoles()
|
||||||
if (!roleHasPermission(roles, PERMISSION.MANAGE_GUILD)) {
|
if (!roleHasPermission(roles, PERMISSION.MANAGE_GUILD)) {
|
||||||
throw new Error('no permission to create bot install tokens')
|
throw new Error('no permission to create bot install tokens')
|
||||||
@@ -2027,6 +2079,7 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
async kickMember ({ userId, reason }) {
|
async kickMember ({ userId, reason }) {
|
||||||
const user = this.identity.user
|
const user = this.identity.user
|
||||||
if (!user || !this.guild?.guild) throw new Error('no guild')
|
if (!user || !this.guild?.guild) throw new Error('no guild')
|
||||||
|
await this._assertStepUp()
|
||||||
const roles = await this._memberRoles()
|
const roles = await this._memberRoles()
|
||||||
if (!roleHasPermission(roles, PERMISSION.MODERATE_MEMBERS)) {
|
if (!roleHasPermission(roles, PERMISSION.MODERATE_MEMBERS)) {
|
||||||
throw new Error('no permission to kick')
|
throw new Error('no permission to kick')
|
||||||
@@ -2053,6 +2106,7 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
async banMember ({ userId, reason }) {
|
async banMember ({ userId, reason }) {
|
||||||
const user = this.identity.user
|
const user = this.identity.user
|
||||||
if (!user || !this.guild?.guild) throw new Error('no guild')
|
if (!user || !this.guild?.guild) throw new Error('no guild')
|
||||||
|
await this._assertStepUp()
|
||||||
const roles = await this._memberRoles()
|
const roles = await this._memberRoles()
|
||||||
if (!roleHasPermission(roles, PERMISSION.MODERATE_MEMBERS)) {
|
if (!roleHasPermission(roles, PERMISSION.MODERATE_MEMBERS)) {
|
||||||
throw new Error('no permission to ban')
|
throw new Error('no permission to ban')
|
||||||
@@ -2332,6 +2386,12 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
? await this.userSettings.getPrefs()
|
? await this.userSettings.getPrefs()
|
||||||
: null
|
: null
|
||||||
const userPrefsStats = this.userSettings?.getStats?.() || null
|
const userPrefsStats = this.userSettings?.getStats?.() || null
|
||||||
|
let stepUpPinSet = false
|
||||||
|
let stepUpUnlocked = false
|
||||||
|
if (this.stepUp) {
|
||||||
|
stepUpPinSet = await this.stepUp.hasPin()
|
||||||
|
stepUpUnlocked = this.stepUp.isSessionActive()
|
||||||
|
}
|
||||||
let dmPeerReadAt = 0
|
let dmPeerReadAt = 0
|
||||||
let dmReadByUser = {}
|
let dmReadByUser = {}
|
||||||
if (this.mode === 'dm' && this.dm?.channel?.id) {
|
if (this.mode === 'dm' && this.dm?.channel?.id) {
|
||||||
@@ -2418,6 +2478,8 @@ class PearcordPlatform extends EventEmitter {
|
|||||||
notificationUnread,
|
notificationUnread,
|
||||||
userPrefs,
|
userPrefs,
|
||||||
userPrefsStats,
|
userPrefsStats,
|
||||||
|
stepUpPinSet,
|
||||||
|
stepUpUnlocked,
|
||||||
searchQuery: this._searchQuery,
|
searchQuery: this._searchQuery,
|
||||||
searchScope: this._searchScope,
|
searchScope: this._searchScope,
|
||||||
searchResults:
|
searchResults:
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
"pearcord-notifications": "git+https://git.ssh.surf/pearcord/pearcord-notifications.git#main",
|
"pearcord-notifications": "git+https://git.ssh.surf/pearcord/pearcord-notifications.git#main",
|
||||||
"pearcord-settings": "git+https://git.ssh.surf/pearcord/pearcord-settings.git#main",
|
"pearcord-settings": "git+https://git.ssh.surf/pearcord/pearcord-settings.git#main",
|
||||||
"pearcord-device-sync": "git+https://git.ssh.surf/pearcord/pearcord-device-sync.git#main",
|
"pearcord-device-sync": "git+https://git.ssh.surf/pearcord/pearcord-device-sync.git#main",
|
||||||
|
"pearcord-step-up": "git+https://git.ssh.surf/pearcord/pearcord-step-up.git#main",
|
||||||
"hyperswarm": "^4.11.6",
|
"hyperswarm": "^4.11.6",
|
||||||
"pearcord-shared": "git+https://git.ssh.surf/pearcord/pearcord-shared.git#main"
|
"pearcord-shared": "git+https://git.ssh.surf/pearcord/pearcord-shared.git#main"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user