Skip to content

Commit

Permalink
Invalidate all sessions by keeping track of session revision
Browse files Browse the repository at this point in the history
  • Loading branch information
Soxasora committed Feb 21, 2025
1 parent c571ba0 commit c9de114
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 0 deletions.
8 changes: 8 additions & 0 deletions api/resolvers/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,14 @@ export default {

await models.user.update({ where: { id: me.id }, data: { hideWelcomeBanner: true } })
return true
},
invalidateSessions: async (parent, args, { me, models }) => {
if (!me) {
throw new GqlAuthenticationError()
}

await models.user.update({ where: { id: me.id }, data: { sessionRev: { increment: 1 } } })
return true
}
},

Expand Down
2 changes: 2 additions & 0 deletions api/typeDefs/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default gql`
generateApiKey(id: ID!): String
deleteApiKey(id: ID!): User
disableFreebies: Boolean
invalidateSessions: Boolean
}
type User {
Expand Down Expand Up @@ -197,6 +198,7 @@ export default gql`
walletsUpdatedAt: Date
proxyReceive: Boolean
directReceive: Boolean
sessionRev: Int
receiveCreditsBelowSats: Int!
sendCreditsBelowSats: Int!
}
Expand Down
2 changes: 2 additions & 0 deletions fragments/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ ${STREAK_FIELDS}
walletsUpdatedAt
proxyReceive
directReceive
sessionRev
}
optional {
isContributor
Expand Down Expand Up @@ -117,6 +118,7 @@ export const SETTINGS_FIELDS = gql`
apiKeyEnabled
proxyReceive
directReceive
sessionRev
receiveCreditsBelowSats
sendCreditsBelowSats
}
Expand Down
6 changes: 6 additions & 0 deletions pages/api/auth/[...nextauth].js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ function getCallbacks (req, res) {
// token won't have an id on it for new logins, we add it
// note: token is what's kept in the jwt
token.id = Number(user.id)
token.sessionRev = user.sessionRev || 0

// if referrer exists, set on user
// isNewUser doesn't work for nostr/lightning auth because we create the user before nextauth can
Expand Down Expand Up @@ -143,6 +144,11 @@ function getCallbacks (req, res) {
// and returns a new object session that's returned whenever get|use[Server]Session is called
session.user.id = token.id

// invalidate this session if session revision mismatch
session.user.sessionRev = token.sessionRev || 0 // if no sessionRev, set to 0, the user will have one after login
const sessionRev = await prisma.user.findUnique({ where: { id: session.user.id }, select: { sessionRev: true } })
if (session.user.sessionRev !== sessionRev?.sessionRev) return {}

return session
}
}
Expand Down
27 changes: 27 additions & 0 deletions pages/settings/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,7 @@ function AuthMethods ({ methods, apiKeyEnabled }) {
)
}
})}
<InvalidateSessions />
<ApiKey apiKey={methods.apiKey} enabled={apiKeyEnabled} />
</>
)
Expand Down Expand Up @@ -1188,3 +1189,29 @@ const TipRandomField = () => {
</>
)
}

const InvalidateSessions = () => {
const showModal = useShowModal()
const router = useRouter()

const [invalidateSessions] = useMutation(gql`
mutation invalidateSessions {
invalidateSessions
}`
)

return (
<Button
variant='danger'
onClick={async () => {
const { data } = await invalidateSessions()
if (data.invalidateSessions) {
// TODO: Invalidate Sessions Obstacle
showModal(onClose => (router.push('/')))
}
}}
>
Invalidate Sessions
</Button>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "users" ADD COLUMN "sessionRev" INTEGER NOT NULL DEFAULT 0;
1 change: 1 addition & 0 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ model User {
mcredits BigInt @default(0)
receiveCreditsBelowSats Int @default(10)
sendCreditsBelowSats Int @default(10)
sessionRev Int @default(0)
muters Mute[] @relation("muter")
muteds Mute[] @relation("muted")
ArcOut Arc[] @relation("fromUser")
Expand Down

0 comments on commit c9de114

Please sign in to comment.