BaseSessionController.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import { ControllerContainerInterface } from '@standardnotes/domain-core'
  2. import { Request, Response } from 'express'
  3. import { BaseHttpController, results } from 'inversify-express-utils'
  4. import { ErrorTag } from '@standardnotes/responses'
  5. import { DeleteOtherSessionsForUser } from '../../../Domain/UseCase/DeleteOtherSessionsForUser'
  6. import { DeleteSessionForUser } from '../../../Domain/UseCase/DeleteSessionForUser'
  7. import { RefreshSessionToken } from '../../../Domain/UseCase/RefreshSessionToken'
  8. import { ResponseLocals } from '../ResponseLocals'
  9. export class BaseSessionController extends BaseHttpController {
  10. constructor(
  11. protected deleteSessionForUser: DeleteSessionForUser,
  12. protected deleteOtherSessionsForUser: DeleteOtherSessionsForUser,
  13. protected refreshSessionToken: RefreshSessionToken,
  14. private controllerContainer?: ControllerContainerInterface,
  15. ) {
  16. super()
  17. if (this.controllerContainer !== undefined) {
  18. this.controllerContainer.register('auth.sessions.delete', this.deleteSession.bind(this))
  19. this.controllerContainer.register('auth.sessions.deleteAll', this.deleteAllSessions.bind(this))
  20. this.controllerContainer.register('auth.sessions.refresh', this.refresh.bind(this))
  21. }
  22. }
  23. async deleteSession(request: Request, response: Response): Promise<results.JsonResult | results.StatusCodeResult> {
  24. const locals = response.locals as ResponseLocals
  25. if (locals.readOnlyAccess) {
  26. return this.json(
  27. {
  28. error: {
  29. tag: ErrorTag.ReadOnlyAccess,
  30. message: 'Session has read-only access.',
  31. },
  32. },
  33. 401,
  34. )
  35. }
  36. if (!request.body.uuid || !locals.session) {
  37. return this.json(
  38. {
  39. error: {
  40. message: 'Please provide the session identifier.',
  41. },
  42. },
  43. 400,
  44. )
  45. }
  46. if (request.body.uuid === locals.session.uuid) {
  47. return this.json(
  48. {
  49. error: {
  50. message: 'You can not delete your current session.',
  51. },
  52. },
  53. 400,
  54. )
  55. }
  56. const useCaseResponse = await this.deleteSessionForUser.execute({
  57. userUuid: locals.user.uuid,
  58. sessionUuid: request.body.uuid,
  59. })
  60. if (!useCaseResponse.success) {
  61. return this.json(
  62. {
  63. error: {
  64. message: useCaseResponse.errorMessage,
  65. },
  66. },
  67. 400,
  68. )
  69. }
  70. response.setHeader('x-invalidate-cache', locals.user.uuid)
  71. return this.statusCode(204)
  72. }
  73. async deleteAllSessions(
  74. _request: Request,
  75. response: Response,
  76. ): Promise<results.JsonResult | results.StatusCodeResult> {
  77. const locals = response.locals as ResponseLocals
  78. if (locals.readOnlyAccess) {
  79. return this.json(
  80. {
  81. error: {
  82. tag: ErrorTag.ReadOnlyAccess,
  83. message: 'Session has read-only access.',
  84. },
  85. },
  86. 401,
  87. )
  88. }
  89. if (!locals.user || !locals.session) {
  90. return this.json(
  91. {
  92. error: {
  93. message: 'No session exists with the provided identifier.',
  94. },
  95. },
  96. 401,
  97. )
  98. }
  99. await this.deleteOtherSessionsForUser.execute({
  100. userUuid: locals.user.uuid,
  101. currentSessionUuid: locals.session.uuid,
  102. markAsRevoked: true,
  103. })
  104. response.setHeader('x-invalidate-cache', locals.user.uuid)
  105. return this.statusCode(204)
  106. }
  107. async refresh(request: Request, response: Response): Promise<results.JsonResult> {
  108. if (!request.body.access_token || !request.body.refresh_token) {
  109. return this.json(
  110. {
  111. error: {
  112. message: 'Please provide all required parameters.',
  113. },
  114. },
  115. 400,
  116. )
  117. }
  118. const result = await this.refreshSessionToken.execute({
  119. accessToken: request.body.access_token,
  120. refreshToken: request.body.refresh_token,
  121. userAgent: <string>request.headers['user-agent'],
  122. })
  123. if (!result.success) {
  124. return this.json(
  125. {
  126. error: {
  127. tag: result.errorTag,
  128. message: result.errorMessage,
  129. },
  130. },
  131. 400,
  132. )
  133. }
  134. response.setHeader('x-invalidate-cache', result.userUuid as string)
  135. return this.json({
  136. session: result.sessionPayload,
  137. })
  138. }
  139. }