Skip to content

Commit c2fd7dd

Browse files
committed
Merge branch 'master' of https://github.com/raghavyuva/nixopus
2 parents 637dbf0 + 03d121a commit c2fd7dd

File tree

6 files changed

+80
-40
lines changed

6 files changed

+80
-40
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# [0.1.0-alpha.68](https://github.com/raghavyuva/nixopus/compare/v0.1.0-alpha.67...v0.1.0-alpha.68) (2025-11-24)
2+
3+
4+
### Bug Fixes
5+
6+
* feature disabled error on signup ([#587](https://github.com/raghavyuva/nixopus/issues/587)) ([8af20ab](https://github.com/raghavyuva/nixopus/commit/8af20abf6c02706e6e726e63da4df7a1399645a3))
7+
8+
9+
110
# [0.1.0-alpha.67](https://github.com/raghavyuva/nixopus/compare/v0.1.0-alpha.66...v0.1.0-alpha.67) (2025-11-21)
211

312

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nixopus",
3-
"version": "0.1.0-alpha.67",
3+
"version": "0.1.0-alpha.68",
44
"description": "A modern container management platform",
55
"private": false,
66
"cli-version": "0.1.26",

version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.1.0-alpha.67
1+
v0.1.0-alpha.68

view/app/register/hooks/use-register.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { useForm } from 'react-hook-form';
99
import { zodResolver } from '@hookform/resolvers/zod';
1010
import * as z from 'zod';
1111
import { useIsAdminRegisteredQuery } from '@/redux/services/users/authApi';
12+
import { useAppDispatch } from '@/redux/hooks';
13+
import { initializeAuth } from '@/redux/features/users/authSlice';
1214

1315
const registerSchema = (t: (key: translationKey, params?: Record<string, string>) => string) =>
1416
z
@@ -36,6 +38,7 @@ type RegisterForm = z.infer<ReturnType<typeof registerSchema>>;
3638
function useRegister() {
3739
const { t } = useTranslation();
3840
const router = useRouter();
41+
const dispatch = useAppDispatch();
3942
const [isLoading, setIsLoading] = useState(false);
4043
const {
4144
data: isAdminRegistered,
@@ -69,6 +72,7 @@ function useRegister() {
6972
toast.error('Sign up is not allowed');
7073
} else {
7174
toast.success(t('auth.register.success'));
75+
await dispatch(initializeAuth() as any);
7276
router.push('/auth');
7377
}
7478
} catch (error) {

view/hooks/socket-provider.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { getWebsocketUrl } from '@/redux/conf';
33
import { createContext, useContext, useEffect, useRef, useState, ReactNode } from 'react';
44
import { getAccessToken } from 'supertokens-auth-react/recipe/session';
5+
import { useAppSelector } from '@/redux/hooks';
56

67
type WebSocketContextValue = {
78
isReady: boolean;
@@ -36,6 +37,7 @@ export const WebSocketProvider = ({
3637
const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
3738
const reconnectAttemptsRef = useRef(0);
3839
const isConnectingRef = useRef(false);
40+
const { isAuthenticated, isInitialized } = useAppSelector((state) => state.auth);
3941

4042
const connectWebSocket = async () => {
4143
if (isConnectingRef.current) {
@@ -127,6 +129,10 @@ export const WebSocketProvider = ({
127129
};
128130

129131
useEffect(() => {
132+
if (!isInitialized || !isAuthenticated) {
133+
return;
134+
}
135+
130136
reconnectAttemptsRef.current = 0;
131137
isConnectingRef.current = false;
132138

@@ -136,12 +142,6 @@ export const WebSocketProvider = ({
136142
}
137143

138144
connectWebSocket();
139-
}, []);
140-
141-
useEffect(() => {
142-
if (!wsRef.current) {
143-
connectWebSocket();
144-
}
145145

146146
return () => {
147147
if (reconnectTimeoutRef.current) {
@@ -159,7 +159,7 @@ export const WebSocketProvider = ({
159159
wsRef.current = null;
160160
}
161161
};
162-
}, []);
162+
}, [isAuthenticated, isInitialized]);
163163

164164
const sendMessage = (data: string) => {
165165
if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {

view/lib/rbac.ts

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { useEffect, useMemo, useState } from 'react';
1+
import { useEffect, useMemo, useState, useCallback, useRef } from 'react';
22
import Session from 'supertokens-web-js/recipe/session';
33
import { UserRoleClaim, PermissionClaim } from 'supertokens-web-js/recipe/userroles';
4+
import { useAppSelector } from '@/redux/hooks';
45

56
export type Resource =
67
| 'organization'
@@ -29,44 +30,70 @@ export const useRBAC = () => {
2930
const [roles, setRoles] = useState<string[] | undefined>(undefined);
3031
const [permissions, setPermissions] = useState<string[] | undefined>(undefined);
3132
const [isLoading, setIsLoading] = useState<boolean>(true);
33+
const { isAuthenticated, isInitialized } = useAppSelector((state) => state.auth);
34+
const activeOrganization = useAppSelector((state) => state.user.activeOrganization);
35+
const retryTimeoutRef = useRef<NodeJS.Timeout | null>(null);
3236

33-
useEffect(() => {
34-
let isMounted = true;
35-
(async () => {
36-
try {
37-
const hasSession = await Session.doesSessionExist();
38-
if (!hasSession) {
39-
if (isMounted) {
40-
setRoles(undefined);
41-
setPermissions(undefined);
42-
setIsLoading(false);
43-
}
44-
return;
45-
}
37+
const fetchRBAC = useCallback(async () => {
38+
try {
39+
if (retryTimeoutRef.current) {
40+
clearTimeout(retryTimeoutRef.current);
41+
retryTimeoutRef.current = null;
42+
}
43+
44+
const hasSession = await Session.doesSessionExist();
45+
if (!hasSession) {
46+
setRoles(undefined);
47+
setPermissions(undefined);
48+
setIsLoading(false);
49+
return;
50+
}
4651

47-
const [sessionRoles, sessionPerms] = await Promise.all([
48-
Session.getClaimValue({ claim: UserRoleClaim }),
49-
Session.getClaimValue({ claim: PermissionClaim })
50-
]);
52+
const [sessionRoles, sessionPerms] = await Promise.all([
53+
Session.getClaimValue({ claim: UserRoleClaim }),
54+
Session.getClaimValue({ claim: PermissionClaim })
55+
]);
5156

52-
if (isMounted) {
53-
setRoles(sessionRoles ?? undefined);
54-
setPermissions(sessionPerms ?? undefined);
55-
setIsLoading(false);
56-
}
57-
} catch (_err) {
58-
if (isMounted) {
59-
setRoles(undefined);
60-
setPermissions(undefined);
61-
setIsLoading(false);
62-
}
57+
if ((!sessionRoles || sessionRoles.length === 0) && (!sessionPerms || sessionPerms.length === 0)) {
58+
retryTimeoutRef.current = setTimeout(() => {
59+
fetchRBAC();
60+
}, 1000);
61+
return;
6362
}
64-
})();
63+
64+
setRoles(sessionRoles ?? undefined);
65+
setPermissions(sessionPerms ?? undefined);
66+
setIsLoading(false);
67+
} catch (err) {
68+
retryTimeoutRef.current = setTimeout(() => {
69+
fetchRBAC();
70+
}, 1000);
71+
}
72+
}, [isAuthenticated, isInitialized, activeOrganization?.id]);
73+
74+
useEffect(() => {
6575
return () => {
66-
isMounted = false;
76+
if (retryTimeoutRef.current) {
77+
clearTimeout(retryTimeoutRef.current);
78+
}
6779
};
6880
}, []);
6981

82+
useEffect(() => {
83+
if (!isInitialized) {
84+
return;
85+
}
86+
87+
if (!isAuthenticated) {
88+
setRoles(undefined);
89+
setPermissions(undefined);
90+
setIsLoading(false);
91+
return;
92+
}
93+
94+
fetchRBAC();
95+
}, [isAuthenticated, isInitialized, activeOrganization?.id, fetchRBAC]);
96+
7097
const isAdmin = useMemo(() => {
7198
if (!Array.isArray(roles)) return false;
7299
return roles.some((role) => {

0 commit comments

Comments
 (0)