CamilleLegeron 2 weeks ago committed by GitHub
commit f2290bd1f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -29,6 +29,9 @@ export class User extends BaseEntity {
@Column({name: 'first_login_at', type: Date, nullable: true})
public firstLoginAt: Date | null;
@Column({name: 'last_connection_at', type: Date, nullable: true})
public lastConnectionAt: Date | null;
@OneToOne(type => Organization, organization => organization.owner)
public personalOrg: Organization;

@ -72,6 +72,7 @@ import {
import uuidv4 from "uuid/v4";
import flatten = require('lodash/flatten');
import pick = require('lodash/pick');
import moment = require('moment-timezone');
// Support transactions in Sqlite in async code. This is a monkey patch, affecting
// the prototypes of various TypeORM classes.
@ -213,6 +214,7 @@ function isNonGuestGroup(group: Group): group is NonGuestGroup {
export interface UserProfileChange {
name?: string;
isFirstTimeUser?: boolean;
newConnection?: boolean;
}
// Identifies a request to access a document. This combination of values is also used for caching
@ -614,6 +616,14 @@ export class HomeDBManager extends EventEmitter {
// any automation for first logins
if (!props.isFirstTimeUser) { isWelcomed = true; }
}
if (props.newConnection === true) {
// set last connection to today (need date only, no time)
const today = moment().startOf('day');
if (today !== moment(user.lastConnectionAt).startOf('day')) {
user.lastConnectionAt = today.toDate();
needsSave = true;
}
}
if (needsSave) {
await user.save();
}

@ -0,0 +1,16 @@
import { MigrationInterface, QueryRunner, TableColumn} from 'typeorm';
export class UserLastConnection1713186031023 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> {
await queryRunner.addColumn('users', new TableColumn({
name: 'last_connection_at',
type: "date",
isNullable: true
}));
}
public async down(queryRunner: QueryRunner): Promise<any> {
await queryRunner.dropColumn('users', 'last_connection_at');
}
}

@ -501,6 +501,10 @@ export class Client {
const user = this._profile ? await this._fetchUser(dbManager) : dbManager.getAnonymousUser();
this._user = user ? dbManager.makeFullUser(user) : undefined;
this._firstLoginAt = user?.firstLoginAt || null;
if (this._user) {
// Send the information to the dbManager that the user has a new activity
await dbManager.updateUser(this._user.id, {newConnection: true});
}
}
private async _onMessage(message: string): Promise<void> {

@ -21,9 +21,9 @@ export const TEST_HTTPS_OFFSET = process.env.GRIST_TEST_HTTPS_OFFSET ?
// Database fields that we permit in entities but don't want to cross the api.
const INTERNAL_FIELDS = new Set([
'apiKey', 'billingAccountId', 'firstLoginAt', 'filteredOut', 'ownerId', 'gracePeriodStart', 'stripeCustomerId',
'stripeSubscriptionId', 'stripePlanId', 'stripeProductId', 'userId', 'isFirstTimeUser', 'allowGoogleLogin',
'authSubject', 'usage', 'createdBy'
'apiKey', 'billingAccountId', 'firstLoginAt', 'lastConnectionAt', 'filteredOut', 'ownerId', 'gracePeriodStart',
'stripeCustomerId', 'stripeSubscriptionId', 'stripePlanId', 'stripeProductId', 'userId', 'isFirstTimeUser',
'allowGoogleLogin', 'authSubject', 'usage', 'createdBy'
]);
/**

@ -41,6 +41,8 @@ import {ForkIndexes1678737195050 as ForkIndexes} from 'app/gen-server/migration/
import {ActivationPrefs1682636695021 as ActivationPrefs} from 'app/gen-server/migration/1682636695021-ActivationPrefs';
import {AssistantLimit1685343047786 as AssistantLimit} from 'app/gen-server/migration/1685343047786-AssistantLimit';
import {Shares1701557445716 as Shares} from 'app/gen-server/migration/1701557445716-Shares';
import {UserLastConnection1713186031023
as UserLastConnection} from 'app/gen-server/migration/1713186031023-UserLastConnection';
const home: HomeDBManager = new HomeDBManager();
@ -49,7 +51,7 @@ const migrations = [Initial, Login, PinDocs, UserPicture, DisplayEmail, DisplayE
CustomerIndex, ExtraIndexes, OrgHost, DocRemovedAt, Prefs,
ExternalBilling, DocOptions, Secret, UserOptions, GracePeriodStart,
DocumentUsage, Activations, UserConnectId, UserUUID, UserUniqueRefUUID,
Forks, ForkIndexes, ActivationPrefs, AssistantLimit, Shares];
Forks, ForkIndexes, ActivationPrefs, AssistantLimit, Shares, UserLastConnection];
// Assert that the "members" acl rule and group exist (or not).
function assertMembersGroup(org: Organization, exists: boolean) {

Loading…
Cancel
Save