1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-10-28 19:06:12 +01:00

feat: ability to configure when users are considered inactive (#8454)

Give the ability to change when users are considered inactive via an
environment variable `USER_INACTIVITY_THRESHOLD_IN_DAYS` or
configuration option: `userInactivityThresholdInDays`. Default remains
180 days
This commit is contained in:
Gastón Fournier 2024-10-15 16:34:04 +02:00 committed by GitHub
parent 6b56f8ff89
commit 7fb9308b3e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 32 additions and 11 deletions

View File

@ -154,6 +154,7 @@ exports[`should create default config 1`] = `
"ui": {
"environment": "Open Source",
},
"userInactivityThresholdInDays": 180,
"versionCheck": {
"enable": true,
"url": "https://version.unleash.run",

View File

@ -713,6 +713,14 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
const openAIAPIKey = process.env.OPENAI_API_KEY;
const defaultDaysToBeConsideredInactive = 180;
const userInactivityThresholdInDays =
options.userInactivityThresholdInDays ??
parseEnvVarNumber(
process.env.USER_INACTIVITY_THRESHOLD_IN_DAYS,
defaultDaysToBeConsideredInactive,
);
return {
db,
session,
@ -752,6 +760,7 @@ export function createConfig(options: IUnleashOptions): IUnleashConfig {
feedbackUriPath,
dailyMetricsStorageDays,
openAIAPIKey,
userInactivityThresholdInDays,
};
}

View File

@ -156,6 +156,7 @@ export interface IUnleashOptions {
| 'segments'
>
>;
userInactivityThresholdInDays?: number;
}
export interface IEmailOption {
@ -274,4 +275,5 @@ export interface IUnleashConfig {
rateLimiting: IRateLimiting;
feedbackUriPath?: string;
openAIAPIKey?: string;
userInactivityThresholdInDays: number;
}

View File

@ -5,30 +5,32 @@ import { InactiveUsersStore } from './inactive-users-store';
import { FakeInactiveUsersStore } from './fakes/fake-inactive-users-store';
import type { UserService } from '../../services';
export const DAYS_TO_BE_COUNTED_AS_INACTIVE = 180;
export const createInactiveUsersService = (
db: Db,
config: IUnleashConfig,
userService: UserService,
): InactiveUsersService => {
const { eventBus, getLogger } = config;
const { eventBus, getLogger, userInactivityThresholdInDays } = config;
const inactiveUsersStore = new InactiveUsersStore(db, eventBus, getLogger);
return new InactiveUsersService(
{ inactiveUsersStore },
{ getLogger },
{ getLogger, userInactivityThresholdInDays },
{ userService },
);
};
export const createFakeInactiveUsersService = (
{ getLogger, eventBus }: Pick<IUnleashConfig, 'getLogger' | 'eventBus'>,
{
getLogger,
userInactivityThresholdInDays,
}: Pick<IUnleashConfig, 'getLogger' | 'userInactivityThresholdInDays'>,
userService: UserService,
): InactiveUsersService => {
const fakeStore = new FakeInactiveUsersStore();
return new InactiveUsersService(
{ inactiveUsersStore: fakeStore },
{ getLogger },
{ getLogger, userInactivityThresholdInDays },
{ userService },
);
};

View File

@ -20,7 +20,6 @@ import {
import type { IAuthRequest } from '../../routes/unleash-types';
import type { Response } from 'express';
import type { OpenApiService } from '../../services';
import { DAYS_TO_BE_COUNTED_AS_INACTIVE } from './createInactiveUsersService';
import { anonymise } from '../../util';
export class InactiveUsersController extends Controller {
private readonly logger: Logger;
@ -30,6 +29,8 @@ export class InactiveUsersController extends Controller {
private openApiService: OpenApiService;
private flagResolver: IFlagResolver;
private readonly userInactivityThresholdInDays: number;
constructor(
config: IUnleashConfig,
{
@ -44,6 +45,8 @@ export class InactiveUsersController extends Controller {
this.inactiveUsersService = inactiveUsersService;
this.openApiService = openApiService;
this.flagResolver = config.flagResolver;
this.userInactivityThresholdInDays =
config.userInactivityThresholdInDays;
this.route({
method: 'get',
@ -54,7 +57,7 @@ export class InactiveUsersController extends Controller {
openApiService.validPath({
operationId: 'getInactiveUsers',
summary: 'Gets inactive users',
description: `Gets all inactive users. An inactive user is a user that has not logged in in the last ${DAYS_TO_BE_COUNTED_AS_INACTIVE} days`,
description: `Gets all inactive users. An inactive user is a user that has not logged in in the last ${this.userInactivityThresholdInDays} days`,
tags: ['Users'],
responses: {
200: createResponseSchema('inactiveUsersSchema'),
@ -71,7 +74,7 @@ export class InactiveUsersController extends Controller {
openApiService.validPath({
operationId: 'deleteInactiveUsers',
summary: 'Deletes inactive users',
description: `Deletes all inactive users. An inactive user is a user that has not logged in in the last ${DAYS_TO_BE_COUNTED_AS_INACTIVE} days`,
description: `Deletes all inactive users. An inactive user is a user that has not logged in in the last ${this.userInactivityThresholdInDays} days`,
tags: ['Users'],
requestBody: createRequestSchema('idsSchema'),
responses: {

View File

@ -8,15 +8,18 @@ import type { IInactiveUsersStore } from './types/inactive-users-store-type';
import type { Logger } from '../../logger';
import type { InactiveUserSchema } from '../../openapi';
import type { UserService } from '../../services';
import { DAYS_TO_BE_COUNTED_AS_INACTIVE } from './createInactiveUsersService';
export class InactiveUsersService {
private inactiveUsersStore: IInactiveUsersStore;
private readonly logger: Logger;
private userService: UserService;
private readonly userInactivityThresholdInDays: number;
constructor(
{ inactiveUsersStore }: Pick<IUnleashStores, 'inactiveUsersStore'>,
{ getLogger }: Pick<IUnleashConfig, 'getLogger'>,
{
getLogger,
userInactivityThresholdInDays,
}: Pick<IUnleashConfig, 'getLogger' | 'userInactivityThresholdInDays'>,
services: {
userService: UserService;
},
@ -24,11 +27,12 @@ export class InactiveUsersService {
this.logger = getLogger('services/client-feature-toggle-service.ts');
this.inactiveUsersStore = inactiveUsersStore;
this.userService = services.userService;
this.userInactivityThresholdInDays = userInactivityThresholdInDays;
}
async getInactiveUsers(): Promise<InactiveUserSchema[]> {
const users = await this.inactiveUsersStore.getInactiveUsers(
DAYS_TO_BE_COUNTED_AS_INACTIVE,
this.userInactivityThresholdInDays,
);
if (users.length > 0) {
return users.map((user) => {