예전에 공부했둔 것 꺼내서 정리했다. Firestore는 Nosql 이라서 대부분의 db코드가 클라에 있고, 그러다 보니 보안을 클라에서만 의존하기에는 불안해서, 서버쪽에서 강화하는쪽으로 고민했었다.
real-groups/{groupId} 는 멤버만 조회할 수 있어야 했다.
real-groups/{groupId}/members/{userId} 의 멤버의 가입은 초대 코드를 알아야만 가입할 수 있다.
이 두 가지 조건을 보안 규칙에 적용해서, 클라이언트에서 잘 못된 호출이나 변조된 호출이 있더라도 데이타를 보호할 수 있도록 했다.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// real
match /real-users/{userId} {
allow create, read, update, delete: if request.auth.uid == userId;
}
match /real-users/{userId}/groups/{groupId} {
allow create, read, update, delete: if request.auth.uid == userId;
}
match /real-open-groups/{groupId} {
// 로그인된 사용자는 생성, 읽기 가능
allow create, read: if request.auth.uid != null;
// 삭제는 document를 만든사람만 가능
allow delete: if get(/databases/$(database)/documents/real-groups/$(groupId)).data.owner == request.auth.uid;
// 업데이트는 document를 만든사람이거나, 이 그룹에 참여한 사람만 가능
allow update: if get(/databases/$(database)/documents/real-groups/$(groupId)).data.owner == request.auth.uid ||
exists(/databases/$(database)/documents/real-groups/$(groupId)/members/$(request.auth.uid));
}
match /real-groups/{groupId} {
allow create: if request.auth.uid != null;
allow delete: if resource.data.owner == request.auth.uid;
allow read, update: if resource.data.owner == request.auth.uid ||
exists(/databases/$(database)/documents/real-groups/$(groupId)/members/$(request.auth.uid));
}
match /real-groups/{groupId}/members/{userId} {
// 멤버추가는 그룹의 관리자이거나, 가입코드를 알고 있는 경우에만 가능
allow create: if get(/databases/$(database)/documents/real-groups/$(groupId)).data.owner == request.auth.uid ||
get(/databases/$(database)/documents/real-groups/$(groupId)).data.code == request.resource.data.code;
// 멤버만 읽기 업데이트 가능
allow read, update: if exists(/databases/$(database)/documents/real-groups/$(groupId)/members/$(request.auth.uid));
// 멤버 삭제는 그룹멤버이면서, 잔고가 0인 경우만 가능
allow delete: if exists(/databases/$(database)/documents/real-groups/$(groupId)/members/$(request.auth.uid)) &&
get(/databases/$(database)/documents/real-groups/$(groupId)/members/$(userId)).data.money == 0;
}
match /real-groups/{groupId}/restaurants/{restId} {
// 식당추가는 그룹 멤버만 가능
allow create, read, update, delete: if exists(/databases/$(database)/documents/real-groups/$(groupId)/members/$(request.auth.uid));
}
}
}