Suppose I have three user groups: admin
, doctor
, and patient
I want both admin
and doctor
to be able to create the type Appointment
, but I want to forbid patient
to do it. To simplify let's suppose that anyone from the 3 groups can read any Appointment
.
Here's the tricky part:
For each Appointment
already created I want the admin group be able to update it and delete it (even if the admin
is not the owner of that Appointment
), but for the doctor
group I want to only allow access to update if the doctor is the owner of the appointment. Besides admin
, I want to let only users in the doctor
group to be able to create Appointment
. The part in bold is what I'm being unable to do. In the schema I have below, patients are also able to create appointments.
How do I change it so that only doctor
and admin
can create?
Note: in Appointment
the create operation for owner
must be there, otherwise, the clientId
field doesn't auto-populate with the owner id, and I need that. I think that create
operation is actually what's creating my problem, but I see no way around.
type Doctor
@model
@auth(
rules: [
{ allow: private, operations: [read] }
{ allow: groups, groups: ["admin"], operations: [create, update, delete] }
{ allow: owner, ownerField: "doctorId", operations: [update] }
]
)
@key(fields: ["doctorId"]) {
doctorId: ID! # This ID won't be auto-populated (it's the cognito pool ID of the doctor)
name: String!
appointments: [Appointment]
@connection(keyName: "byDoctor", fields: ["doctorId"])
createdAt: String
}
type Patient
@model
@auth(
rules: [
{ allow: private, operations: [read] }
{ allow: groups, groups: ["admin"], operations: [create, update, delete] }
{ allow: owner, ownerField: "patientId", operations: [update] }
]
)
@key(fields: ["patientId"]) {
patientId: ID! # This ID won't be auto-populated (it's the cognito pool ID of the patient)
name: String!
appointments: [Appointment]
@connection(keyName: "byPatient", fields: ["patientId"])
createdAt: String
}
type Appointment
@model
@auth(
rules: [
{ allow: private, operations: [read] }
{ allow: groups, groups: ["admin"], operations: [create, update, delete] }
{ allow: groups, groups: ["doctor"], operations: [create, read] }
{ allow: owner, ownerField: "doctorId", operations: [create, update] }
]
)
@key(
name: "byDoctor"
fields: ["doctorId", "createdAt"]
queryField: "appointmentsByDoctorId"
)
@key(
name: "byPatient"
fields: ["patientId", "createdAt"]
queryField: "appointmentsByPatientId"
) {
id: ID!
doctorId: ID # Auto-populated with cognito pool ID of the doctor
patientId: ID!
doctor: Doctor @connection(fields: ["doctorId"])
patient: Patient @connection(fields: ["patientId"])
createdAt: String
}
And here's an illustration of the problem:
# -- Initially authenticated as a user in `admin` group --
# Result: initially empty (which is expected)
query ListAppointments {
listAppointments {
items {
id
doctorId
patientId
}
}
}
# Result: succeeds (which is expected)
mutation CreateDoctor {
createDoctor(input: {
doctorId: "66a2b382-952d-4e8d-a25e-b8d1876e8017" # arbitrary
name: "Doctor 1"
}) {
doctorId
name
}
}
# Result: succeeds (which is expected)
mutation CreatePatient {
createPatient(input: {
patientId: "2d9366cd-165b-4437-a910-647900df0587" # arbitrary
name: "Bar Patient"
}) {
patientId
name
}
}
# -- Switching auth to user in `doctor` group --
# Result: succeeds (which is expected)
# If we run `ListAppointments` now, the appointment created is there
mutation CreateAppointmentByDoctor {
createAppointment(input: {
patientId: "8a2b382-952d-4e8d-a25e-b8d187000000" # arbitrary
}) {
id
}
}
# -- Switching auth to user in `patient` group --
# Result: succeeds (which is NOT expected)
# If we run `ListAppointments` now, there are two appointments there,
# including this one created by a client
mutation CreateAppointmentByPatient {
createAppointment(input: {
patientId: "8a2b382-952d-4e8d-a25e-b8d187001000" #arbitrary
}) {
id
}
}