Kaynağa Gözat

fix(home-server): allow custom atributtes for activating premium features

Karol Sójko 1 yıl önce
ebeveyn
işleme
f7190c0c9c

+ 5 - 1
packages/auth/src/Bootstrap/AuthServiceInterface.ts

@@ -1,5 +1,9 @@
 import { Result, ServiceInterface } from '@standardnotes/domain-core'
 import { Result, ServiceInterface } from '@standardnotes/domain-core'
 
 
 export interface AuthServiceInterface extends ServiceInterface {
 export interface AuthServiceInterface extends ServiceInterface {
-  activatePremiumFeatures(username: string): Promise<Result<string>>
+  activatePremiumFeatures(dto: {
+    username: string
+    subscriptionPlanName?: string
+    endsAt?: Date
+  }): Promise<Result<string>>
 }
 }

+ 6 - 2
packages/auth/src/Bootstrap/Service.ts

@@ -24,14 +24,18 @@ export class Service implements AuthServiceInterface {
     this.serviceContainer.register(this.getId(), this)
     this.serviceContainer.register(this.getId(), this)
   }
   }
 
 
-  async activatePremiumFeatures(username: string): Promise<Result<string>> {
+  async activatePremiumFeatures(dto: {
+    username: string
+    subscriptionPlanName?: string
+    endsAt?: Date
+  }): Promise<Result<string>> {
     if (!this.container) {
     if (!this.container) {
       return Result.fail('Container not initialized')
       return Result.fail('Container not initialized')
     }
     }
 
 
     const activatePremiumFeatures = this.container.get(TYPES.Auth_ActivatePremiumFeatures) as ActivatePremiumFeatures
     const activatePremiumFeatures = this.container.get(TYPES.Auth_ActivatePremiumFeatures) as ActivatePremiumFeatures
 
 
-    return activatePremiumFeatures.execute({ username })
+    return activatePremiumFeatures.execute(dto)
   }
   }
 
 
   async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> {
   async handleRequest(request: never, response: never, endpointOrMethodIdentifier: string): Promise<unknown> {

+ 24 - 0
packages/auth/src/Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures.spec.ts

@@ -75,4 +75,28 @@ describe('ActivatePremiumFeatures', () => {
     expect(userSubscriptionRepository.save).toHaveBeenCalled()
     expect(userSubscriptionRepository.save).toHaveBeenCalled()
     expect(roleService.addUserRole).toHaveBeenCalled()
     expect(roleService.addUserRole).toHaveBeenCalled()
   })
   })
+
+  it('should save a subscription with custom plan name and endsAt', async () => {
+    const useCase = createUseCase()
+
+    const result = await useCase.execute({
+      username: 'test@test.te',
+      subscriptionPlanName: 'PRO_PLAN',
+      endsAt: new Date('2024-01-01T00:00:00.000Z'),
+    })
+
+    expect(result.isFailed()).toBe(false)
+  })
+
+  it('should fail when subscription plan name is invalid', async () => {
+    const useCase = createUseCase()
+
+    const result = await useCase.execute({
+      username: 'test@test.te',
+      subscriptionPlanName: 'some invalid plan name',
+      endsAt: new Date('2024-01-01T00:00:00.000Z'),
+    })
+
+    expect(result.isFailed()).toBe(true)
+  })
 })
 })

+ 11 - 3
packages/auth/src/Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeatures.ts

@@ -30,22 +30,30 @@ export class ActivatePremiumFeatures implements UseCaseInterface<string> {
     if (user === null) {
     if (user === null) {
       return Result.fail(`User not found with username: ${username.value}`)
       return Result.fail(`User not found with username: ${username.value}`)
     }
     }
+    const subscriptionPlanNameString = dto.subscriptionPlanName ?? SubscriptionPlanName.NAMES.ProPlan
+    const subscriptionPlanNameOrError = SubscriptionPlanName.create(subscriptionPlanNameString)
+    if (subscriptionPlanNameOrError.isFailed()) {
+      return Result.fail(subscriptionPlanNameOrError.getError())
+    }
+    const subscriptionPlanName = subscriptionPlanNameOrError.getValue()
 
 
     const timestamp = this.timer.getTimestampInMicroseconds()
     const timestamp = this.timer.getTimestampInMicroseconds()
 
 
+    const endsAt = dto.endsAt ?? this.timer.getUTCDateNDaysAhead(365)
+
     const subscription = new UserSubscription()
     const subscription = new UserSubscription()
-    subscription.planName = SubscriptionPlanName.NAMES.ProPlan
+    subscription.planName = subscriptionPlanName.value
     subscription.user = Promise.resolve(user)
     subscription.user = Promise.resolve(user)
     subscription.createdAt = timestamp
     subscription.createdAt = timestamp
     subscription.updatedAt = timestamp
     subscription.updatedAt = timestamp
-    subscription.endsAt = this.timer.convertDateToMicroseconds(this.timer.getUTCDateNDaysAhead(365))
+    subscription.endsAt = this.timer.convertDateToMicroseconds(endsAt)
     subscription.cancelled = false
     subscription.cancelled = false
     subscription.subscriptionId = 1
     subscription.subscriptionId = 1
     subscription.subscriptionType = UserSubscriptionType.Regular
     subscription.subscriptionType = UserSubscriptionType.Regular
 
 
     await this.userSubscriptionRepository.save(subscription)
     await this.userSubscriptionRepository.save(subscription)
 
 
-    await this.roleService.addUserRole(user, SubscriptionPlanName.NAMES.ProPlan)
+    await this.roleService.addUserRole(user, subscriptionPlanName.value)
 
 
     await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
     await this.subscriptionSettingService.applyDefaultSubscriptionSettingsForSubscription(
       subscription,
       subscription,

+ 2 - 0
packages/auth/src/Domain/UseCase/ActivatePremiumFeatures/ActivatePremiumFeaturesDTO.ts

@@ -1,3 +1,5 @@
 export interface ActivatePremiumFeaturesDTO {
 export interface ActivatePremiumFeaturesDTO {
   username: string
   username: string
+  subscriptionPlanName?: string
+  endsAt?: Date
 }
 }

+ 11 - 3
packages/home-server/src/Server/HomeServer.ts

@@ -141,7 +141,11 @@ export class HomeServer implements HomeServerInterface {
 
 
         if (env.get('E2E_TESTING', true) === 'true') {
         if (env.get('E2E_TESTING', true) === 'true') {
           app.post('/e2e/activate-premium', (request: Request, response: Response) => {
           app.post('/e2e/activate-premium', (request: Request, response: Response) => {
-            void this.activatePremiumFeatures(request.body.username).then((result) => {
+            void this.activatePremiumFeatures({
+              username: request.body.username,
+              subscriptionPlanName: request.body.subscriptionPlanName,
+              endsAt: request.body.endsAt ? new Date(request.body.endsAt) : undefined,
+            }).then((result) => {
               if (result.isFailed()) {
               if (result.isFailed()) {
                 response.status(400).send({ error: { message: result.getError() } })
                 response.status(400).send({ error: { message: result.getError() } })
               } else {
               } else {
@@ -212,12 +216,16 @@ export class HomeServer implements HomeServerInterface {
     return this.serverInstance.address() !== null
     return this.serverInstance.address() !== null
   }
   }
 
 
-  async activatePremiumFeatures(username: string): Promise<Result<string>> {
+  async activatePremiumFeatures(dto: {
+    username: string
+    subscriptionPlanName?: string
+    endsAt?: Date
+  }): Promise<Result<string>> {
     if (!this.isRunning() || !this.authService) {
     if (!this.isRunning() || !this.authService) {
       return Result.fail('Home server is not running.')
       return Result.fail('Home server is not running.')
     }
     }
 
 
-    return this.authService.activatePremiumFeatures(username)
+    return this.authService.activatePremiumFeatures(dto)
   }
   }
 
 
   private configureLoggers(env: Env, configuration: HomeServerConfiguration): void {
   private configureLoggers(env: Env, configuration: HomeServerConfiguration): void {

+ 5 - 1
packages/home-server/src/Server/HomeServerInterface.ts

@@ -3,7 +3,11 @@ import { HomeServerConfiguration } from './HomeServerConfiguration'
 
 
 export interface HomeServerInterface {
 export interface HomeServerInterface {
   start(configuration?: HomeServerConfiguration): Promise<Result<string>>
   start(configuration?: HomeServerConfiguration): Promise<Result<string>>
-  activatePremiumFeatures(username: string): Promise<Result<string>>
+  activatePremiumFeatures(dto: {
+    username: string
+    subscriptionPlanName?: string
+    endsAt?: Date
+  }): Promise<Result<string>>
   stop(): Promise<Result<string>>
   stop(): Promise<Result<string>>
   isRunning(): Promise<boolean>
   isRunning(): Promise<boolean>
 }
 }