From 46c09fc5fa4887bc4ba934e4f309327d14cf9a6a Mon Sep 17 00:00:00 2001 From: shreddedbacon Date: Wed, 21 Jun 2023 15:52:25 +1000 Subject: [PATCH 1/2] feat: add resolver to get user by ssh key fingerprint --- services/api/src/resolvers.js | 2 ++ services/api/src/resources/user/resolvers.ts | 22 ++++++++++++++++++++ services/api/src/resources/user/sql.ts | 10 +++++++++ services/api/src/typeDefs.js | 4 ++++ 4 files changed, 38 insertions(+) diff --git a/services/api/src/resolvers.js b/services/api/src/resolvers.js index b62b5128e9..756c236762 100644 --- a/services/api/src/resolvers.js +++ b/services/api/src/resolvers.js @@ -207,6 +207,7 @@ const { const { getMe, getUserBySshKey, + getUserBySshFingerprint, addUser, updateUser, deleteUser, @@ -464,6 +465,7 @@ const resolvers = { me: getMe, lagoonVersion: getLagoonVersion, userBySshKey: getUserBySshKey, + userBySshFingerprint: getUserBySshFingerprint, projectByGitUrl: getProjectByGitUrl, projectByName: getProjectByName, environmentsByKubernetes: getEnvironmentsByKubernetes, diff --git a/services/api/src/resources/user/resolvers.ts b/services/api/src/resources/user/resolvers.ts index 364004617e..f690a2d94a 100644 --- a/services/api/src/resources/user/resolvers.ts +++ b/services/api/src/resources/user/resolvers.ts @@ -44,6 +44,28 @@ export const getUserBySshKey: ResolverFn = async ( return user; }; +export const getUserBySshFingerprint: ResolverFn = async ( + _root, + { fingerprint }, + { sqlClientPool, models, hasPermission }, +) => { + await hasPermission('user', 'getBySshKey'); + + if(!fingerprint) { + throw new SearchInputError("Malformed ssh key fingerprint provided"); + } + + const rows = await query( + sqlClientPool, + Sql.selectUserIdBySshFingerprint({keyFingerprint: fingerprint}), + ); + const userId = R.map(R.prop('usid'), rows); + + const user = await models.UserModel.loadUserById(userId); + + return user; +}; + // query to get all users, with some inputs to limit the search to specific email, id, or gitlabId export const getAllUsers: ResolverFn = async ( _root, diff --git a/services/api/src/resources/user/sql.ts b/services/api/src/resources/user/sql.ts index 1e3143b754..a5b2ed46c4 100644 --- a/services/api/src/resources/user/sql.ts +++ b/services/api/src/resources/user/sql.ts @@ -14,4 +14,14 @@ export default { .andWhere('sk.key_type', keyType) .select('user_ssh_key.usid') .toString(), + selectUserIdBySshFingerprint: ({ + keyFingerprint, + }: { + keyFingerprint: string; + }): string => + knex('user_ssh_key') + .join('ssh_key as sk', 'sk.id', '=', 'user_ssh_key.skid') + .where('sk.key_fingerprint', keyFingerprint) + .select('user_ssh_key.usid') + .toString(), }; diff --git a/services/api/src/typeDefs.js b/services/api/src/typeDefs.js index eb4bfb3af9..4cc7336c0a 100644 --- a/services/api/src/typeDefs.js +++ b/services/api/src/typeDefs.js @@ -1098,6 +1098,10 @@ const typeDefs = gql` """ userBySshKey(sshKey: String!): User """ + Returns User Object by a given sshKey Fingerprint + """ + userBySshFingerprint(fingerprint: String!): User + """ Returns User Object by a given email address """ userByEmail(email: String!): User From 03b3bc2f449b2ef54f1ec10b395fc828233ae6e0 Mon Sep 17 00:00:00 2001 From: shreddedbacon Date: Thu, 22 Jun 2023 07:57:17 +1000 Subject: [PATCH 2/2] chore: add errors if no user found --- services/api/src/resources/user/resolvers.ts | 28 +++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/services/api/src/resources/user/resolvers.ts b/services/api/src/resources/user/resolvers.ts index f690a2d94a..bd613765cf 100644 --- a/services/api/src/resources/user/resolvers.ts +++ b/services/api/src/resources/user/resolvers.ts @@ -15,6 +15,13 @@ class SearchInputError extends Error { } } +class UserNotFoundError extends Error { + constructor(message: string) { + super(message); + this.name = 'UserNotFoundError'; + } +} + export const getUserBySshKey: ResolverFn = async ( _root, @@ -54,16 +61,17 @@ export const getUserBySshFingerprint: ResolverFn = async ( if(!fingerprint) { throw new SearchInputError("Malformed ssh key fingerprint provided"); } - - const rows = await query( - sqlClientPool, - Sql.selectUserIdBySshFingerprint({keyFingerprint: fingerprint}), - ); - const userId = R.map(R.prop('usid'), rows); - - const user = await models.UserModel.loadUserById(userId); - - return user; + try { + const rows = await query( + sqlClientPool, + Sql.selectUserIdBySshFingerprint({keyFingerprint: fingerprint}), + ); + const userId = R.map(R.prop('usid'), rows); + const user = await models.UserModel.loadUserById(userId); + return user; + } catch (err) { + throw new UserNotFoundError("No user found matching provided fingerprint"); + } }; // query to get all users, with some inputs to limit the search to specific email, id, or gitlabId