Skip to content

Commit

Permalink
tl-its-umich-edu#252 - check for user existence
Browse files Browse the repository at this point in the history
@ssciolla: I'm not sure whether I wrote this API entry with the security we would like.  Give me feedback.
  • Loading branch information
lsloan committed Dec 20, 2021
1 parent 32f9fe0 commit 761c3d0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 2 deletions.
36 changes: 35 additions & 1 deletion ccm_web/server/src/api/api.admin.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { APIErrorData, isAPIErrorData } from './api.interfaces'
import { handleAPIError, HttpMethod, makeResponse } from './api.utils'
import {
CanvasAccount,
CanvasCourse, CanvasUser,
CanvasCourse,
CanvasUser,
CourseWithSections,
CourseWorkflowState
} from '../canvas/canvas.interfaces'
Expand Down Expand Up @@ -176,4 +177,37 @@ export class AdminApiHandler {

return createUserResponses
}

async getUserInfo (loginId: string): Promise<CanvasUser | APIErrorData> {
const safeLoginId = loginId.replace('@', '+')

try {
const endpoint = `users/sis_login_id:${safeLoginId}`
const method = HttpMethod.Get
logger.debug(`Sending admin request to Canvas endpoint: "${endpoint}"; method: "${method}"`)
const response = await this.requestor.get<CanvasUser>(endpoint)
logger.debug(`Received response with status code (${String(response.statusCode)})`)
const {
id,
name,
sortable_name, // eslint-disable-line
short_name // eslint-disable-line
} = response.body
return {
id,
name,
sortable_name,
short_name,
login_id: loginId,
email: undefined as any
}
} catch (error) {
const errorResponse = handleAPIError(error, `Login ID: ${loginId}`)
return {
statusCode: errorResponse.canvasStatusCode,
errors: [errorResponse]
}
}

}
}
12 changes: 11 additions & 1 deletion ccm_web/server/src/api/api.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { SectionUserDto, SectionUsersDto } from './dtos/api.section.users.dto'
import { JwtAuthGuard } from '../auth/jwt-auth.guard'
import { SessionGuard } from '../auth/session.guard'
import {
CanvasCourseBase, CanvasCourseSection, CanvasCourseSectionBase, CanvasEnrollment, CourseWithSections
CanvasCourseBase, CanvasCourseSection, CanvasCourseSectionBase, CanvasEnrollment, CourseWithSections, CanvasUser
} from '../canvas/canvas.interfaces'
import { InvalidTokenInterceptor } from '../canvas/invalid.token.interceptor'
import { UserDec } from '../user/user.decorator'
Expand Down Expand Up @@ -103,6 +103,16 @@ export class APIController {
return result
}

@UseInterceptors(InvalidTokenInterceptor) @Get('admin/user/:loginId')
async getUserInfoAsAdmin (
@Param('loginId') loginId: string,
@UserDec() user: User
): Promise<CanvasUser> {
const result = await this.apiService.getUserInfoAsAdmin(user, loginId)
if (isAPIErrorData(result)) throw new HttpException(result, result.statusCode)
return result
}

@UseInterceptors(InvalidTokenInterceptor)
@Get('instructor/sections')
async getCourseSectionsInTermAsInstructor (
Expand Down
6 changes: 6 additions & 0 deletions ccm_web/server/src/api/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ export class APIService {
})
}

async getUserInfoAsAdmin (user: User, loginId: string): Promise<CanvasUser | APIErrorData> {
const adminRequestor = this.canvasService.createRequestorForAdmin('/api/v1/')
const adminHandler = new AdminApiHandler(adminRequestor, user.loginId)
return await adminHandler.getUserInfo(loginId)
}

async mergeSections (user: User, targetCourseId: number, sectionIds: number[]): Promise<CanvasCourseSectionBase[] | APIErrorData> {
const requestor = await this.canvasService.createRequestorForUser(user, '/api/v1/')
const courseHandler = new CourseApiHandler(requestor, targetCourseId)
Expand Down

0 comments on commit 761c3d0

Please sign in to comment.