Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
11bf743
step 1: add backend models for DAU claim
shivoomiess Jun 24, 2026
eebd948
chore: comments + planning wip
shivoomiess Jun 26, 2026
e8785bf
add: DB patch for DAU claim
shivoomiess Jun 26, 2026
0a440d4
add: DAU claim datasources
shivoomiess Jun 26, 2026
690a838
add: modify DAU datasources to allow propagate accept invite changes
shivoomiess Jun 26, 2026
3c248cd
add: Dependency injection changes due to DAU claims
shivoomiess Jun 26, 2026
eef7581
add: more datasource related functions for invites
shivoomiess Jun 30, 2026
440df87
add: mirror CoProposer invite business logic for DAU
shivoomiess Jun 30, 2026
c981fa5
add: events for DAU invites and email template
shivoomiess Jun 30, 2026
e9f2506
add: frontend changes for DAU invite
shivoomiess Jun 30, 2026
5bb0f15
add: dataAccessInvites to where Proposal is built
shivoomiess Jun 30, 2026
b7732bc
refactor: Show invited for Co-Proposers and DAU inline on Proposal
shivoomiess Jun 30, 2026
ce7c095
fix: use correct auth for DAU
shivoomiess Jun 30, 2026
f132108
fix: read invite relevant proposal for both co-prop & DAU
shivoomiess Jun 30, 2026
e9637ee
fix: changes from review suggestions
shivoomiess Jul 2, 2026
ef2df9d
fix: try catch block for DB errors,
shivoomiess Jul 3, 2026
4a8e52d
fix: fetch DA users without institution, remove redundant user details
shivoomiess Jul 3, 2026
709560c
fix: LF to CRLF
shivoomiess Jul 3, 2026
311bab1
feat(backend): auto-accept DAU invite onLogin flow to mirror
shivoomiess Jul 6, 2026
4259b93
feat(frontend): auto-accept DAU invite onLogin flow to mirror Co
shivoomiess Jul 6, 2026
7cce30e
refactor: UI changes for invite list
shivoomiess Jul 6, 2026
ce44522
Merge branch 'develop' into SWAP-5408-invite-DAU
shivoomiess Jul 7, 2026
e32e88d
Merge branch 'develop' into SWAP-5408-invite-DAU
yoganandaness Jul 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions apps/backend/db_patches/0213_AddDataAccessClaims.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
DO
$$
BEGIN
IF register_patch('0213_AddDataAccessClaims', 'Shivam K', 'Adding data access user claims', '2026-06-26') THEN
BEGIN
CREATE TABLE IF NOT EXISTS data_access_claims (
invite_id INT NOT NULL REFERENCES invites(invite_id) ON DELETE CASCADE,
proposal_pk INT NOT NULL REFERENCES proposals(proposal_pk) ON DELETE CASCADE,
PRIMARY KEY (invite_id, proposal_pk));
END;
END IF;
END;
$$
LANGUAGE plpgsql;
1 change: 1 addition & 0 deletions apps/backend/src/config/Tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export const Tokens = {
ConfigureEnvironment: Symbol('ConfigureEnvironment'),
ConfigureLogger: Symbol('ConfigureLogger'),
CoProposerClaimDataSource: Symbol('CoProposerClaimDataSource'),
DataAccessClaimDataSource: Symbol('DataAccessClaimDataSource'),
DataAccessUsersDataSource: Symbol('DataAccessUsersDataSource'),
DataAccessUsersAuthorization: Symbol('DataAccessUsersAuthorization'),
EmailEventHandler: Symbol('EmailEventHandler'),
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/config/dependencyConfigDLS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { VisitRegistrationAuthorization } from '../auth/VisitRegistrationAuthori
import { PostgresAdminDataSourceWithAutoUpgrade } from '../datasources/postgres/AdminDataSource';
import PostgresCallDataSource from '../datasources/postgres/CallDataSource';
import PostgresCoProposerClaimDataSource from '../datasources/postgres/CoProposerClaimDataSource';
import PostgresDataAccessClaimDataSource from '../datasources/postgres/DataAccessClaimDataSource';
import PostgresDataAccessUsersDataSource from '../datasources/postgres/DataAccessUsersDataSource';
import PostgresEmailTemplateDataSource from '../datasources/postgres/EmailTemplateDataSource';
import PostgresEventLogsDataSource from '../datasources/postgres/EventLogsDataSource';
Expand Down Expand Up @@ -66,6 +67,7 @@ import { SkipAssetRegistrar } from '../services/assetRegistrar/skip/SkipAssetReg

mapClass(Tokens.AdminDataSource, PostgresAdminDataSourceWithAutoUpgrade);
mapClass(Tokens.CoProposerClaimDataSource, PostgresCoProposerClaimDataSource);
mapClass(Tokens.DataAccessClaimDataSource, PostgresDataAccessClaimDataSource);
mapClass(Tokens.DataAccessUsersDataSource, PostgresDataAccessUsersDataSource);
mapClass(Tokens.CallDataSource, PostgresCallDataSource);
mapClass(Tokens.EventLogsDataSource, PostgresEventLogsDataSource);
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/config/dependencyConfigDefault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { mapClass, mapValue } from './utils';
import { PostgresAdminDataSourceWithAutoUpgrade } from '../datasources/postgres/AdminDataSource';
import PostgresCallDataSource from '../datasources/postgres/CallDataSource';
import PostgresCoProposerClaimDataSource from '../datasources/postgres/CoProposerClaimDataSource';
import PostgresDataAccessClaimDataSource from '../datasources/postgres/DataAccessClaimDataSource';
import PostgresDataAccessUsersDataSource from '../datasources/postgres/DataAccessUsersDataSource';
import PostgresEmailTemplateDataSource from '../datasources/postgres/EmailTemplateDataSource';
import PostgresEventLogsDataSource from '../datasources/postgres/EventLogsDataSource';
Expand Down Expand Up @@ -75,6 +76,7 @@ async function skipEmailHandler(event: ApplicationEvent) {
mapClass(Tokens.RoleDataSource, PostgresRoleDataSource);
mapClass(Tokens.AdminDataSource, PostgresAdminDataSourceWithAutoUpgrade);
mapClass(Tokens.CoProposerClaimDataSource, PostgresCoProposerClaimDataSource);
mapClass(Tokens.DataAccessClaimDataSource, PostgresDataAccessClaimDataSource);
mapClass(Tokens.DataAccessUsersDataSource, PostgresDataAccessUsersDataSource);
mapClass(Tokens.CallDataSource, PostgresCallDataSource);
mapClass(Tokens.EventLogsDataSource, PostgresEventLogsDataSource);
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/config/dependencyConfigE2E.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { mapClass, mapValue } from './utils';
import PostgresAdminDataSource from '../datasources/postgres/AdminDataSource';
import PostgresCallDataSource from '../datasources/postgres/CallDataSource';
import PostgresCoProposerClaimDataSource from '../datasources/postgres/CoProposerClaimDataSource';
import PostgresDataAccessClaimDataSource from '../datasources/postgres/DataAccessClaimDataSource';
import PostgresDataAccessUsersDataSource from '../datasources/postgres/DataAccessUsersDataSource';
import PostgresEmailTemplateDataSource from '../datasources/postgres/EmailTemplateDataSource';
import PostgresEventLogsDataSource from '../datasources/postgres/EventLogsDataSource';
Expand Down Expand Up @@ -67,6 +68,7 @@ import { SkipAssetRegistrar } from '../services/assetRegistrar/skip/SkipAssetReg
mapClass(Tokens.RoleDataSource, PostgresRoleDataSource);
mapClass(Tokens.AdminDataSource, PostgresAdminDataSource);
mapClass(Tokens.CoProposerClaimDataSource, PostgresCoProposerClaimDataSource);
mapClass(Tokens.DataAccessClaimDataSource, PostgresDataAccessClaimDataSource);
mapClass(Tokens.DataAccessUsersDataSource, PostgresDataAccessUsersDataSource);
mapClass(Tokens.CallDataSource, PostgresCallDataSource);
mapClass(Tokens.EventLogsDataSource, PostgresEventLogsDataSource);
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/config/dependencyConfigELI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { mapClass, mapValue } from './utils';
import { PostgresAdminDataSourceWithAutoUpgrade } from '../datasources/postgres/AdminDataSource';
import PostgresCallDataSource from '../datasources/postgres/CallDataSource';
import PostgresCoProposerClaimDataSource from '../datasources/postgres/CoProposerClaimDataSource';
import PostgresDataAccessClaimDataSource from '../datasources/postgres/DataAccessClaimDataSource';
import PostgresDataAccessUsersDataSource from '../datasources/postgres/DataAccessUsersDataSource';
import PostgresEmailTemplateDataSource from '../datasources/postgres/EmailTemplateDataSource';
import PostgresEventLogsDataSource from '../datasources/postgres/EventLogsDataSource';
Expand Down Expand Up @@ -69,6 +70,7 @@ const isProduction = process.env.NODE_ENV === 'production';
mapClass(Tokens.RoleDataSource, PostgresRoleDataSource);
mapClass(Tokens.AdminDataSource, PostgresAdminDataSourceWithAutoUpgrade);
mapClass(Tokens.CoProposerClaimDataSource, PostgresCoProposerClaimDataSource);
mapClass(Tokens.DataAccessClaimDataSource, PostgresDataAccessClaimDataSource);
mapClass(Tokens.DataAccessUsersDataSource, PostgresDataAccessUsersDataSource);
mapClass(Tokens.CallDataSource, PostgresCallDataSource);
mapClass(Tokens.EventLogsDataSource, PostgresEventLogsDataSource);
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/config/dependencyConfigESS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getSecondsFromAllocationTimeUnits } from './base/allocationTimeUnitConv
import { PostgresAdminDataSourceWithAutoUpgrade } from '../datasources/postgres/AdminDataSource';
import PostgresCallDataSource from '../datasources/postgres/CallDataSource';
import PostgresCoProposerClaimDataSource from '../datasources/postgres/CoProposerClaimDataSource';
import PostgresDataAccessClaimDataSource from '../datasources/postgres/DataAccessClaimDataSource';
import PostgresDataAccessUsersDataSource from '../datasources/postgres/DataAccessUsersDataSource';
import PostgresEmailTemplateDataSource from '../datasources/postgres/EmailTemplateDataSource';
import PostgresEventLogsDataSource from '../datasources/postgres/EventLogsDataSource';
Expand Down Expand Up @@ -69,6 +70,7 @@ import { mapClass, mapValue } from './utils';
mapClass(Tokens.RoleDataSource, PostgresRoleDataSource);
mapClass(Tokens.AdminDataSource, PostgresAdminDataSourceWithAutoUpgrade);
mapClass(Tokens.CoProposerClaimDataSource, PostgresCoProposerClaimDataSource);
mapClass(Tokens.DataAccessClaimDataSource, PostgresDataAccessClaimDataSource);
mapClass(Tokens.DataAccessUsersDataSource, PostgresDataAccessUsersDataSource);
mapClass(Tokens.CallDataSource, PostgresCallDataSource);
mapClass(Tokens.EventLogsDataSource, PostgresEventLogsDataSource);
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/config/dependencyConfigSTFC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { mapClass, mapValue } from './utils';
import { PostgresAdminDataSourceWithAutoUpgrade } from '../datasources/postgres/AdminDataSource';
import PostgresCallDataSource from '../datasources/postgres/CallDataSource';
import PostgresCoProposerClaimDataSource from '../datasources/postgres/CoProposerClaimDataSource';
import PostgresDataAccessClaimDataSource from '../datasources/postgres/DataAccessClaimDataSource';
import PostgresDataAccessUsersDataSource from '../datasources/postgres/DataAccessUsersDataSource';
import PostgresEmailTemplateDataSource from '../datasources/postgres/EmailTemplateDataSource';
import PostgresEventLogsDataSource from '../datasources/postgres/EventLogsDataSource';
Expand Down Expand Up @@ -67,6 +68,7 @@ import { SkipAssetRegistrar } from '../services/assetRegistrar/skip/SkipAssetReg
mapClass(Tokens.RoleDataSource, PostgresRoleDataSource);
mapClass(Tokens.AdminDataSource, PostgresAdminDataSourceWithAutoUpgrade);
mapClass(Tokens.CoProposerClaimDataSource, PostgresCoProposerClaimDataSource);
mapClass(Tokens.DataAccessClaimDataSource, PostgresDataAccessClaimDataSource);
mapClass(Tokens.DataAccessUsersDataSource, PostgresDataAccessUsersDataSource);
mapClass(Tokens.CallDataSource, PostgresCallDataSource);
mapClass(Tokens.EventLogsDataSource, PostgresEventLogsDataSource);
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/config/dependencyConfigTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { getSecondsFromAllocationTimeUnits } from './base/allocationTimeUnitConv
import { AdminDataSourceMock } from '../datasources/mockups/AdminDataSource';
import { CallDataSourceMock } from '../datasources/mockups/CallDataSource';
import { CoProposerClaimDataSourceMock } from '../datasources/mockups/CoProposerClaimDataSource';
import { DataAccessClaimDataSourceMock } from '../datasources/mockups/DataAccessClaimDataSource';
import MockDataAccessUsersDataSource from '../datasources/mockups/DataAccessUsersDataSource';
import { EmailTemplateDataSourceMock } from '../datasources/mockups/EmailTemplateDataSource';
import { EventLogsDataSourceMock } from '../datasources/mockups/EventLogsDataSource';
Expand Down Expand Up @@ -61,6 +62,7 @@ import { mapClass, mapValue } from './utils';
mapClass(Tokens.RoleDataSource, RoleDataSourceMock);
mapClass(Tokens.AdminDataSource, AdminDataSourceMock);
mapClass(Tokens.CoProposerClaimDataSource, CoProposerClaimDataSourceMock);
mapClass(Tokens.DataAccessClaimDataSource, DataAccessClaimDataSourceMock);
mapClass(Tokens.DataAccessUsersDataSource, MockDataAccessUsersDataSource);
mapClass(Tokens.CallDataSource, CallDataSourceMock);
mapClass(Tokens.EventLogsDataSource, EventLogsDataSourceMock);
Expand Down
7 changes: 7 additions & 0 deletions apps/backend/src/datasources/DataAccessClaimDataSource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { DataAccessClaim } from '../models/DataAccessClaim';

export interface DataAccessClaimDataSource {
create(inviteId: number, proposalPk: number): Promise<DataAccessClaim>;
findByInviteId(inviteId: number): Promise<DataAccessClaim[]>;
findByProposalPk(proposalPk: number): Promise<DataAccessClaim[]>;
}
8 changes: 8 additions & 0 deletions apps/backend/src/datasources/DataAccessUsersDataSource.ts
Comment thread
shivoomiess marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,20 @@ export type UserWithInstitution = {

export interface DataAccessUsersDataSource {
findByProposalPk(proposalPk: number): Promise<BasicUserDetails[]>;

getDataAccessUsersWithInstitution(
proposalPk: number
): Promise<UserWithInstitution[]>;

addDataAccessUser(
proposalPk: number,
userId: number
): Promise<Rejection | undefined>;

updateDataAccessUsers(
proposalPk: number,
userIds: number[]
): Promise<BasicUserDetails[] | Rejection>;

isDataAccessUserOfProposal(id: number, proposalPk: number): Promise<boolean>;
}
9 changes: 7 additions & 2 deletions apps/backend/src/datasources/InviteDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface GetInvitesFilter {
email?: string;
}

export interface GetCoProposerInvitesFilter extends GetInvitesFilter {
export interface GetProposalInvitesFilter extends GetInvitesFilter {
proposalPk?: number;
}

Expand All @@ -27,12 +27,17 @@ export interface InviteDataSource {
proposalPk: number,
isClaimed?: boolean
): Promise<Invite[]>;
findDataAccessInvites(
proposalPk: number,
isClaimed?: boolean
): Promise<Invite[]>;
findVisitRegistrationInvites(
visitId: number,
isClaimed?: boolean
): Promise<Invite[]>;
getInvites(filter: GetInvitesFilter): Promise<Invite[]>;
getCoProposerInvites(filter: GetCoProposerInvitesFilter): Promise<Invite[]>;
getCoProposerInvites(filter: GetProposalInvitesFilter): Promise<Invite[]>;
getDataAccessInvites(filter: GetProposalInvitesFilter): Promise<Invite[]>;

update(args: {
id: number;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { DataAccessClaim } from '../../models/DataAccessClaim';
import { DataAccessClaimDataSource } from '../DataAccessClaimDataSource';

export class DataAccessClaimDataSourceMock
implements DataAccessClaimDataSource
{
private invites: DataAccessClaim[] = [];

init() {
this.invites = [
new DataAccessClaim(7, 1), // use IDs unique from coproposal invites
new DataAccessClaim(8, 2),
new DataAccessClaim(9, 3),
];
}

async findByProposalPk(proposalPk: number): Promise<DataAccessClaim[]> {
return this.invites.filter((invite) => invite.proposalPk === proposalPk);
}

async findByInviteId(inviteId: number): Promise<DataAccessClaim[]> {
return this.invites.filter((invite) => invite.inviteId === inviteId);
}

async create(inviteId: number, proposalPk: number): Promise<DataAccessClaim> {
const newInvite = new DataAccessClaim(inviteId, proposalPk);

this.invites.push(newInvite);

return newInvite;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export const dummyInstitution2 = new Institution(11, 'Research Center', 2);

export const dummyCountry = new Country(1, 'Denmark');
export const dummyCountry2 = new Country(2, 'United Kingdom');
export const dummyCountry3 = new Country(3, 'Belarus');

export default class MockDataAccessUsersDataSource
implements DataAccessUsersDataSource
Expand Down Expand Up @@ -121,4 +122,33 @@ export default class MockDataAccessUsersDataSource

return Promise.resolve(userIds.includes(id));
}

async addDataAccessUser(
proposalPk: number,
userId: number
): Promise<Rejection | undefined> {
try {
const existingUserIds = this.mockData.get(proposalPk) || [];

// Idempotent insert - don't add the same user twice
if (!existingUserIds.includes(userId)) {
this.mockData.set(proposalPk, [...existingUserIds, userId]);
}

const users = await this.findByProposalPk(proposalPk);
const addedUser = users.find((user) => user.id === userId);

if (!addedUser) {
throw new Error(`No mock user found for id ${userId}`);
}

return;
} catch (error) {
return new Rejection('Failed to add data access user', {
proposalPk,
userId,
error: error instanceof Error ? error.message : String(error),
});
}
}
}
Loading
Loading