【发布时间】:2019-12-02 13:18:50
【问题描述】:
我正在构建一个管理用户和班次的 Android 应用。每个用户可以分配到多个班次,每个班次可以有多个用户。每个班次都与一个日期相关联。
这就是我的数据库在 firebase 中的结构:
{
"shift-assign" : {
"key1" : {
"111" : true,
"222" : true,
"888" : true
},
"key2" : {
"111" : true,
"222" : true
}
},
"shifts" : {
"key1" : {
"date" : "20191202",
"endTime" : "02:00",
"numOfEmps" : 4,
"startTime" : "21:00",
"wage" : 30
},
"key2" : {
"date" : "20191202",
"endTime" : "12:00",
"numOfEmps" : 3,
"startTime" : "08:00",
"wage" : 10
},
"key3" : {
"date" : "20191203",
"endTime" : "06:00",
"numOfEmps" : 3,
"startTime" : "00:00",
"wage" : 30
}
},
"user-assign" : {
"111" : {
"key1" : true,
"key2" : true
},
"222" : {
"key1" : true,
"key2" : true
},
"888" : {
"key1" : true
}
},
"users" : {
"111" : {
"active" : true,
"email" : "111",
"firstName" : "aaa",
"id" : "111",
"lastName" : "aaa",
"password" : "111",
"phone" : "1111111"
},
"222" : {
"active" : true,
"email" : "222",
"firstName" : "bbb",
"id" : "222",
"lastName" : "bbb",
"password" : "222",
"phone" : "4444444"
},
"888" : {
"active" : false,
"email" : "888",
"firstName" : "ccc",
"id" : "888",
"lastName" : "ccc",
"password" : "888",
"phone" : "5555555"
},
"99999" : {
"active" : true,
"firstName" : "Admin",
"id" : "99999",
"password" : "123"
}
}
}
当用户尝试将自己分配到班次时,我想在实际分配到班次之前检查一些约束。
我尝试使用事务,但代码搞砸了,因为我需要在事务中引用不同的节点。
我的代码现在看起来像这样:
private void AssignUserToShift() {
// Constraint No. 0
// user cannot be assigned to shifts whose date < today
if(dates[0].compareTo(LocalDateTime.now().toLocalDate().format(dtf)) < 0){
Toast.makeText(getApplicationContext(), "Cannot assign to prior dates", Toast.LENGTH_SHORT).show();
return;
}
Map<String, Object> pathsToUpdate = new HashMap<>();
pathsToUpdate.put("shift-assign/" + shiftKey + "/" + userId, true);
pathsToUpdate.put("user-assign/" + userId + "/" + shiftKey, true);
mDatabase.updateChildren(pathsToUpdate, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(@Nullable DatabaseError databaseError, @NonNull DatabaseReference databaseReference) {
if(databaseError == null) {
// add to adapter's list in GUI
AddUserToList();
}else{
Toast.makeText(getApplicationContext(), "Could not update database entries", Toast.LENGTH_SHORT).show();
}
}
});
}
和相反的方法:
private void RemoveUserFromShift() {
mUser user = userList.stream()
.filter(u -> u.getId().equals(userId))
.findAny()
.orElse(null);
if(user == null){
Toast.makeText(UsersAssignedActivity.this, "You are not assigned to this shift.", Toast.LENGTH_SHORT).show();
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(UsersAssignedActivity.this, R.style.AlertDialogCustom);
builder.setMessage("Do you wish to remove yourself from this shift?");
builder.setCancelable(false);
builder.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int i) {
Map<String, Object> pathsToDelete = new HashMap<>();
pathsToDelete.put("shift-assign/" + shiftKey + "/" + userId, null);
pathsToDelete.put("user-assign/" + userId + "/" + shiftKey, null);
mDatabase.updateChildren(pathsToDelete, new DatabaseReference.CompletionListener() {
@Override
public void onComplete(@Nullable DatabaseError databaseError, @NonNull DatabaseReference databaseReference) {
if(databaseError == null){
// remove from adapter's list in GUI
RemoveUserFromList();
}else{
Toast.makeText(UsersAssignedActivity.this, "Could not delete database entries", Toast.LENGTH_SHORT).show();
}
}
});
}
});
builder.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int i) {
dialog.cancel();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
所以我想我会改用规则并检查服务器端的约束。
我想写满足以下条件的规则——
用户不能分配到已满的班次。 (其
numOfEmps等于shift-assign/shiftKey下的子节点数)-
用户在某个日期不能分配超过一半的班次(如果同一日期有 4 个班次,并且用户已经被分配到其中一个班次,他们将只被允许分配在该日期再分配一个班次。)
-
用户不得连续工作超过 4 天。 (如果用户尝试将自己分配到某个日期的班次,并且用户在过去 4 天内已分配到班次,则他们将无法将自己分配到该班次)
最后,如果用户尚未分配到此班次。我想这可以在客户端使用事务进行检查。
-
如何编写这些规则?
【问题讨论】:
标签: java android firebase firebase-realtime-database firebase-security