forked from ytgov/internal-data-portal
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #40 from icefoganalytics/issue-38/part-2/data-owne…
…r-add-ability-to-define-access-constraints Part 2: Data Owner: Add Ability To Define Access Constraints
- Loading branch information
Showing
55 changed files
with
1,858 additions
and
141 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { WhereOptions } from "sequelize" | ||
|
||
import { AccessRequest } from "@/models" | ||
import { TableSerializer } from "@/serializers/access-requests" | ||
|
||
import BaseController from "@/controllers/base-controller" | ||
|
||
export class AccessRequestsController extends BaseController { | ||
async index() { | ||
const where = this.query.where as WhereOptions<AccessRequest> | ||
|
||
const totalCount = await AccessRequest.count({ where }) | ||
const accessRequests = await AccessRequest.findAll({ | ||
where, | ||
include: [ | ||
{ | ||
association: "requestor", | ||
include: [ | ||
{ | ||
association: "groupMembership", | ||
include: ["department"], | ||
}, | ||
], | ||
}, | ||
"accessGrant", | ||
], | ||
limit: this.pagination.limit, | ||
offset: this.pagination.offset, | ||
order: [["requestor", "firstName", "ASC"]], | ||
}) | ||
|
||
try { | ||
const serializedAccessRequests = TableSerializer.perform(accessRequests, this.currentUser) | ||
return this.response.json({ accessRequests: serializedAccessRequests, totalCount }) | ||
} catch (error) { | ||
return this.response | ||
.status(500) | ||
.json({ message: `Failed to serialize access requests: ${error}` }) | ||
} | ||
} | ||
} | ||
|
||
export default AccessRequestsController |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { isNil } from "lodash" | ||
|
||
import { AccessRequest } from "@/models" | ||
import { AccessRequestsPolicy } from "@/policies" | ||
import { ApproveService } from "@/services/access-requests" | ||
import { type AccessRequestWithDataset } from "@/policies/access-requests-policy" | ||
|
||
import BaseController from "@/controllers/base-controller" | ||
|
||
export class ApproveController extends BaseController { | ||
async create() { | ||
const accessRequest = await this.loadAccessRequest() | ||
if (isNil(accessRequest)) { | ||
return this.response.status(404).json({ message: "Access request not found." }) | ||
} | ||
|
||
const policy = this.buildPolicy(accessRequest) | ||
if (!policy.update()) { | ||
return this.response | ||
.status(403) | ||
.json({ message: "You are not authorized to approve access requests on this dataset." }) | ||
} | ||
|
||
try { | ||
const updatedAccessRequest = await ApproveService.perform(accessRequest, this.currentUser) | ||
return this.response.status(200).json({ accessRequest: updatedAccessRequest }) | ||
} catch (error) { | ||
return this.response.status(422).json({ message: `Access request approval failed: ${error}` }) | ||
} | ||
} | ||
|
||
private async loadAccessRequest(): Promise<AccessRequestWithDataset | null> { | ||
const { accessRequestId } = this.request.params | ||
const accessRequest = await AccessRequest.findByPk(accessRequestId, { include: ["dataset"] }) | ||
if (isNil(accessRequest?.dataset)) return null | ||
|
||
// TODO: figure out how to make this type cast unneccessary | ||
return accessRequest as AccessRequestWithDataset | ||
} | ||
|
||
private buildPolicy(accessRequest: AccessRequestWithDataset) { | ||
return new AccessRequestsPolicy(this.currentUser, accessRequest) | ||
} | ||
} | ||
|
||
export default ApproveController |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { isNil } from "lodash" | ||
|
||
import { AccessRequest } from "@/models" | ||
import { AccessRequestsPolicy } from "@/policies" | ||
import { AccessRequestWithDataset } from "@/policies/access-requests-policy" | ||
import { DenyService } from "@/services/access-requests" | ||
|
||
import BaseController from "@/controllers/base-controller" | ||
|
||
export class DenyController extends BaseController { | ||
async create() { | ||
const accessRequest = await this.loadAccessRequest() | ||
if (isNil(accessRequest)) { | ||
return this.response.status(404).json({ message: "Access request not found." }) | ||
} | ||
|
||
const policy = this.buildPolicy(accessRequest) | ||
if (!policy.update()) { | ||
return this.response | ||
.status(403) | ||
.json({ message: "You are not authorized to deny access requests on this dataset." }) | ||
} | ||
|
||
const permittedAttributes = policy.permitAttributes(this.request.body) | ||
try { | ||
const updatedAccessRequest = await DenyService.perform( | ||
accessRequest, | ||
permittedAttributes, | ||
this.currentUser | ||
) | ||
return this.response.status(200).json({ accessRequest: updatedAccessRequest }) | ||
} catch (error) { | ||
return this.response.status(422).json({ message: `Access request denial failed: ${error}` }) | ||
} | ||
} | ||
|
||
private async loadAccessRequest(): Promise<AccessRequestWithDataset | null> { | ||
const { accessRequestId } = this.request.params | ||
const accessRequest = await AccessRequest.findByPk(accessRequestId, { include: ["dataset"] }) | ||
if (isNil(accessRequest?.dataset)) return null | ||
|
||
// TODO: figure out how to make this type cast unneccessary | ||
return accessRequest as AccessRequestWithDataset | ||
} | ||
|
||
private buildPolicy(accessRequest: AccessRequestWithDataset) { | ||
return new AccessRequestsPolicy(this.currentUser, accessRequest) | ||
} | ||
} | ||
|
||
export default DenyController |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { ApproveController } from "./approve-controller" | ||
export { DenyController } from "./deny-controller" | ||
export { RevokeController } from "./revoke-controller" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { isNil } from "lodash" | ||
|
||
import { AccessRequest } from "@/models" | ||
import { AccessRequestsPolicy } from "@/policies" | ||
import { AccessRequestWithDataset } from "@/policies/access-requests-policy" | ||
import { RevokeService } from "@/services/access-requests" | ||
|
||
import BaseController from "@/controllers/base-controller" | ||
|
||
export class RevokeController extends BaseController { | ||
async create() { | ||
const accessRequest = await this.loadAccessRequest() | ||
if (isNil(accessRequest)) { | ||
return this.response.status(404).json({ message: "Access request not found." }) | ||
} | ||
|
||
const policy = this.buildPolicy(accessRequest) | ||
if (!policy.update()) { | ||
return this.response | ||
.status(403) | ||
.json({ message: "You are not authorized to revoke access requests on this dataset." }) | ||
} | ||
|
||
try { | ||
const updatedAccessRequest = await RevokeService.perform(accessRequest, this.currentUser) | ||
return this.response.status(200).json({ accessRequest: updatedAccessRequest }) | ||
} catch (error) { | ||
return this.response.status(422).json({ message: `Access request revokal failed: ${error}` }) | ||
} | ||
} | ||
|
||
private async loadAccessRequest(): Promise<AccessRequestWithDataset | null> { | ||
const { accessRequestId } = this.request.params | ||
const accessRequest = await AccessRequest.findByPk(accessRequestId, { include: ["dataset"] }) | ||
if (isNil(accessRequest?.dataset)) return null | ||
|
||
// TODO: figure out how to make this type cast unneccessary | ||
return accessRequest as AccessRequestWithDataset | ||
} | ||
|
||
private buildPolicy(accessRequest: AccessRequestWithDataset) { | ||
return new AccessRequestsPolicy(this.currentUser, accessRequest) | ||
} | ||
} | ||
|
||
export default RevokeController |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.