Skip to content

Commit

Permalink
Merge pull request #451 from bcgov/development
Browse files Browse the repository at this point in the history
dev into master
  • Loading branch information
bdolor authored Dec 15, 2023
2 parents 7da5eb9 + d728887 commit 6803ae1
Show file tree
Hide file tree
Showing 59 changed files with 2,437 additions and 446 deletions.
2 changes: 1 addition & 1 deletion openshift/templates/backup/backup-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ objects:
backup.conf: |-
postgres=${DATABASE_SERVICE_NAME}:${DATABASE_PORT}/${DATABASE_NAME}
0 */6 * * * default ./backup.sh -s
0 2 * * * default ./backup.sh -s
parameters:
- name: DATABASE_SERVICE_NAME
Expand Down
8 changes: 4 additions & 4 deletions openshift/templates/backup/backup-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,14 @@ parameters:
description: The number of weekly backup files to be retained. Used for the `rolling`
backup strategy.
required: false
value: '4'
value: '3'

- name: MONTHLY_BACKUPS
displayName: Number of Monthly Backups to Retain
description: The number of monthly backup files to be retained. Used for the `rolling`
backup strategy.
required: false
value: '1'
value: '0'

- name: BACKUP_PERIOD
displayName: Period (d,m,s) between backups in a format used by the sleep command
Expand Down Expand Up @@ -356,7 +356,7 @@ parameters:
1Gi, 2Gi. Ensure this is sized correctly. Refer to the container documentation
for details.
required: true
value: 10Gi
value: 30Gi

- name: BACKUP_VOLUME_CLASS
displayName: Backup Volume Class
Expand All @@ -383,7 +383,7 @@ parameters:
backups, e.g. 512Mi, 1Gi, 2Gi. Ensure this is sized correctly. It should be
large enough to contain your largest database.
required: true
value: 10Gi
value: 30Gi

- name: VERIFICATION_VOLUME_CLASS
displayName: Backup Volume Class
Expand Down
146 changes: 120 additions & 26 deletions src/back-end/lib/db/affiliation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import { readOneUser } from "back-end/lib/db/user";
import { valid } from "shared/lib/http";
import {
Affiliation,
AffiliationEvent,
AffiliationHistoryRecord,
AffiliationMember,
AffiliationSlim,
MembershipStatus,
MembershipType
} from "shared/lib/resources/affiliation";
import { Session } from "shared/lib/resources/session";
import { AuthenticatedSession, Session } from "shared/lib/resources/session";
import { User } from "shared/lib/resources/user";
import { Id } from "shared/lib/types";
import { getValidValue } from "shared/lib/validation";
Expand All @@ -32,6 +34,16 @@ interface RawAffiliation {
updatedAt: Date;
}

type OrgIds = Id[];

export interface RawHistoryRecord
extends Omit<AffiliationHistoryRecord, "createdBy" | "member" | "type"> {
id: Id;
createdBy: Id;
event: AffiliationEvent;
affiliation: Id;
}

async function rawAffiliationToAffiliation(
connection: Connection,
params: RawAffiliation
Expand Down Expand Up @@ -122,8 +134,8 @@ export const readOneAffiliation = tryDb<[Id, Id], Affiliation | null>(
}
);

export const readOneAffiliationById = tryDb<[Id], Affiliation | null>(
async (connection, id) => {
export const readOneAffiliationById = tryDb<[Id, boolean?], Affiliation | null>(
async (connection, id, activeOnly = true) => {
const result = await connection<RawAffiliation>("affiliations")
.join(
"organizations",
Expand All @@ -134,7 +146,9 @@ export const readOneAffiliationById = tryDb<[Id], Affiliation | null>(
.select<RawAffiliation>("affiliations.*")
.where({ "affiliations.id": id })
.andWhereNot({
"affiliations.membershipStatus": MembershipStatus.Inactive,
...(activeOnly
? { "affiliations.membershipStatus": MembershipStatus.Inactive }
: {}),
"organizations.active": false
})
.first();
Expand Down Expand Up @@ -248,29 +262,64 @@ export const approveAffiliation = tryDb<[Id], Affiliation>(
}
);

export const updateAdminStatus = tryDb<[Id, MembershipType], Affiliation>(
async (connection, id, membershipType: MembershipType) => {
export const updateAdminStatus = tryDb<
[Id, MembershipType, AuthenticatedSession],
Affiliation
>(
async (
connection,
id,
membershipType: MembershipType,
session: AuthenticatedSession
) => {
const now = new Date();
const [result] = await connection<RawAffiliation>("affiliations")
.update(
{
membershipType,
updatedAt: now
} as RawAffiliation,
"*"
)
.where({
id
})
.whereIn("organization", function () {
this.select("id").from("organizations").where({
active: true
return await connection.transaction(async (trx) => {
const [affiliation] = await connection<RawAffiliation>("affiliations")
.transacting(trx)
.update(
{
membershipType,
updatedAt: now
} as RawAffiliation,
"*"
)
.where({
id
})
.whereIn("organization", function () {
this.select("id").from("organizations").where({
active: true
});
});
});
if (!result) {
throw new Error("unable to update admin status");
}
return valid(await rawAffiliationToAffiliation(connection, result));

if (!affiliation) {
throw new Error("unable to update admin status");
}

const [affiliationEvent] = await connection<RawHistoryRecord>(
"affiliationEvents"
)
.transacting(trx)
.insert(
{
id: generateUuid(),
affiliation: affiliation.id,
event:
membershipType === MembershipType.Admin
? AffiliationEvent.AdminStatusGranted
: AffiliationEvent.AdminStatusRevoked,
createdAt: now,
createdBy: session.user.id
},
"*"
);

if (!affiliationEvent) {
throw new Error("unable to create affiliation event");
}

return valid(await rawAffiliationToAffiliation(connection, affiliation));
});
}
);

Expand Down Expand Up @@ -300,9 +349,14 @@ export const deleteAffiliation = tryDb<[Id], Affiliation>(
}
);

/**
*
* @param membershipType
* @returns boolean
*/
function makeIsUserTypeChecker(
membershipType: MembershipType
): (connection: Connection, user: User, ordId: Id) => Promise<boolean> {
): (connection: Connection, user: User, orgId: Id) => Promise<boolean> {
return async (connection: Connection, user: User, orgId: Id) => {
if (!user) {
return false;
Expand All @@ -323,6 +377,15 @@ const isUserAdminOfOrg = makeIsUserTypeChecker(MembershipType.Admin);

export const isUserOwnerOfOrg = makeIsUserTypeChecker(MembershipType.Owner);

/**
* If you have the orgId and user you can check if they are either an ADMIN or
* OWNER of an organization
*
* @param connection
* @param user
* @param orgId
* @returns Promise<boolean>
*/
export const isUserOwnerOrAdminOfOrg = async (
connection: Connection,
user: User,
Expand Down Expand Up @@ -355,3 +418,34 @@ export async function readActiveOwnerCount(
return 0;
}
}

/**
* Checks to see if a user has a memberStatus that is active and a membershipType
* that is either Admin or Owner.
*
* @param connection - Knex connection
* @param userId - unique identifier for user
* @returns Promise<OrgIds> - Returns an object of organizationIds or null.
*/
export async function getOrgIdsForOwnerOrAdmin(
connection: Connection,
userId: Id
): Promise<OrgIds> {
const result = await connection("affiliations")
.distinct<OrgIds>("organization")
.where("membershipStatus", "ACTIVE")
.andWhere(function () {
this.where({
"affiliations.membershipType": MembershipType.Admin
}).orWhere({
"affiliations.membershipType": MembershipType.Owner
});
})
.andWhere("user", userId)
.pluck("organization");

if (!result) {
throw new Error("unable to process orgIds for Owner or Admin");
}
return result;
}
Loading

0 comments on commit 6803ae1

Please sign in to comment.