Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating user management flyway migrations #367

Merged
merged 13 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions query-connector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ Our e2e's are available locally via `npm run test:playwright:local`. You'll need

For flows that do queries to a FHIR server (ie `/query`), you'll need to use a DB utility to change the address of the local E2E server to whatever localhost port your dev HAPI server is living at. If you have questions, reach out to another eng on the team.

### Query Connector ERD

![Query Connector Database Structure](public/Query%20Connector%20ERD.drawio.svg)

### Architecture Diagram

```mermaid
Expand Down
42 changes: 42 additions & 0 deletions query-connector/flyway/sql/V07_01__update_user_management.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
CREATE TABLE IF NOT EXISTS users (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
username TEXT NOT NULL UNIQUE,
qc_role TEXT,
first_name TEXT,
last_name TEXT
);

CREATE TABLE IF NOT EXISTS usergroup (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
name TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS usergroup_to_users (
id TEXT PRIMARY KEY,
user_id UUID,
usergroup_id UUID,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (usergroup_id) REFERENCES usergroup(id)
);

CREATE TABLE IF NOT EXISTS usergroup_to_query (
id TEXT PRIMARY KEY,
query_id UUID,
usergroup_id UUID,
FOREIGN KEY (query_id) REFERENCES query(id),
FOREIGN KEY (usergroup_id) REFERENCES usergroup(id)
);

-- Create indexes for ids and foreign keys
CREATE INDEX IF NOT EXISTS user_id_index ON users (id);
CREATE INDEX IF NOT EXISTS user_username_index ON users (username);

CREATE INDEX IF NOT EXISTS usergroup_id_index ON usergroup (id);

CREATE INDEX IF NOT EXISTS usergroup_to_users_id_index ON usergroup_to_users (id);
CREATE INDEX IF NOT EXISTS usergroup_to_users_user_id_index ON usergroup_to_users (user_id);
CREATE INDEX IF NOT EXISTS usergroup_to_users_usergroup_id_index ON usergroup_to_users (usergroup_id);

CREATE INDEX IF NOT EXISTS usergroup_to_query_id_index ON usergroup_to_query (id);
CREATE INDEX IF NOT EXISTS usergroup_to_query_query_id_index ON usergroup_to_query (query_id);
CREATE INDEX IF NOT EXISTS usergroup_to_query_usergroup_id_index ON usergroup_to_query (usergroup_id);
4 changes: 4 additions & 0 deletions query-connector/public/Query Connector ERD.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 22 additions & 27 deletions query-connector/src/app/backend/user-management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { getDbClient } from "./dbClient";
const dbClient = getDbClient();

/**
* Adds a user to the user_management table if they do not already exist.
* Adds a user to the users table if they do not already exist.
* Uses data extracted from the JWT token.
* @param userToken - The user data from the JWT token.
* @param userToken.id - The user ID from the JWT token.
Expand All @@ -30,25 +30,25 @@ export async function addUserIfNotExists(userToken: {
const userIdentifier = username || email;

try {
console.log("Checking if user exists:", id);
console.log("Checking if user exists.");

const checkUserQuery = `SELECT username FROM user_management WHERE username = $1;`;
const checkUserQuery = `SELECT id, username FROM users WHERE username = $1;`;
const userExists = await dbClient.query(checkUserQuery, [userIdentifier]);

if (userExists.rows.length > 0) {
console.log("User already exists in user_management:", id);
return userExists.rows[0];
console.log("User already exists in users:", userExists.rows[0].id);
return userExists.rows[0]; // Return existing user
}

console.log("User not found. Proceeding to insert:", id);
console.log("User not found. Proceeding to insert.");

// Default role when adding a new user, which includer Super Admin, Admin, and Standard User.
// Default role when adding a new user, which includes Super Admin, Admin, and Standard User.
const qc_role = "Standard User";

const insertUserQuery = `
INSERT INTO user_management (username, qc_role, first_name, last_name)
INSERT INTO users (username, qc_role, first_name, last_name)
VALUES ($1, $2, $3, $4)
RETURNING username, qc_role, first_name, last_name;
RETURNING id, username, qc_role, first_name, last_name;
`;

const result = await dbClient.query(insertUserQuery, [
Expand All @@ -58,42 +58,37 @@ export async function addUserIfNotExists(userToken: {
lastName,
]);

console.log("User added to user_management", id);
console.log("User added to users:", result.rows[0].id);
return result.rows[0];
} catch (error) {
console.error("Error adding user to user_management:", error);
console.error("Error adding user to users:", error);
throw error;
}
}

/**
* Updates the role of an existing user in the user_management table.
* @param id - The user ID from the JWT token.
* @param username - The username of the user whose role is being updated.
* Updates the role of an existing user in the users table.
* @param id - The user ID.
* @param newRole - The new role to assign to the user.
* @returns The updated user record or an error if the update fails.
*/
export async function updateUserRole(
id: string,
username: string,
newRole: string,
) {
if (!id || !username || !newRole) {
console.error("Invalid input: id, username, and newRole are required.");
throw new Error("User ID, username, and new role are required.");
export async function updateUserRole(id: string, newRole: string) {
if (!id || !newRole) {
console.error("Invalid input: id and newRole are required.");
throw new Error("User ID and new role are required.");
}

try {
console.log(`Updating role for user: ${id} to ${newRole}`);
console.log(`Updating role for user ID: ${id} to ${newRole}`);

const updateQuery = `
UPDATE user_management
UPDATE users
SET qc_role = $1
WHERE username = $2
RETURNING username, qc_role, first_name, last_name;
WHERE id = $2
RETURNING id, username, qc_role, first_name, last_name;
`;

const result = await dbClient.query(updateQuery, [newRole, username]);
const result = await dbClient.query(updateQuery, [newRole, id]);

if (result.rows.length === 0) {
console.error(`User not found: ${id}`);
Expand Down
Loading
Loading