({ project }: IAMRemindDialogProps)
| 28 | } |
| 29 | |
| 30 | export function IAMRemindDialog({ project }: IAMRemindDialogProps) { |
| 31 | const { t } = useTranslation(); |
| 32 | const route = useCurrentRoute(); |
| 33 | const navigate = useNavigate(); |
| 34 | const currentUser = useAppStore((state) => state.currentUser); |
| 35 | const isSaaS = useAppStore((state) => state.isSaaSMode()); |
| 36 | const roles = useAppStore((state) => state.roles); |
| 37 | const policy = useAppStore( |
| 38 | (state) => state.projectPoliciesByName[project.name] |
| 39 | ); |
| 40 | const [checked, setChecked] = useState(false); |
| 41 | const [open, setOpen] = useState(false); |
| 42 | |
| 43 | const pendingExpireRoles = useMemo(() => { |
| 44 | if (!policy || !currentUser) return []; |
| 45 | const roleByName = new Map(roles.map((role) => [role.name, role])); |
| 46 | const now = Date.now(); |
| 47 | const expiresBefore = now + 2 * 24 * 60 * 60 * 1000; |
| 48 | return bindingMatchesUser(policy, currentUser) |
| 49 | .map((binding) => { |
| 50 | const role = roleByName.get(binding.role); |
| 51 | const expiration = getBindingExpirationDate(binding); |
| 52 | return role && expiration ? { role, expiration } : undefined; |
| 53 | }) |
| 54 | .filter((item): item is NonNullable<typeof item> => Boolean(item)) |
| 55 | .filter(({ expiration }) => { |
| 56 | const time = expiration.getTime(); |
| 57 | return time > now && time < expiresBefore; |
| 58 | }) |
| 59 | .sort((a, b) => a.expiration.getTime() - b.expiration.getTime()); |
| 60 | }, [currentUser, policy, roles]); |
| 61 | |
| 62 | const storageKey = currentUser?.email |
| 63 | ? storageKeyIamRemind( |
| 64 | workspaceCacheScope(isSaaS, currentUser.workspace), |
| 65 | currentUser.email |
| 66 | ) |
| 67 | : ""; |
| 68 | const remindKey = |
| 69 | pendingExpireRoles.length > 0 |
| 70 | ? `${project.name}.${pendingExpireRoles |
| 71 | .map(({ role }) => role.name) |
| 72 | .join("&")}` |
| 73 | : ""; |
| 74 | const isInProjectPage = route.fullPath.startsWith(`/${project.name}`); |
| 75 | |
| 76 | useEffect(() => { |
| 77 | if (!storageKey || !remindKey) { |
| 78 | setOpen(false); |
| 79 | return; |
| 80 | } |
| 81 | const state = readJson<Record<string, boolean>>(storageKey, {}); |
| 82 | if (!(remindKey in state)) { |
| 83 | writeJson(storageKey, { ...state, [remindKey]: true }); |
| 84 | setOpen(true); |
| 85 | return; |
| 86 | } |
| 87 | setOpen(state[remindKey] ?? false); |
nothing calls this directly
no test coverage detected