Compare commits
No commits in common. "5a70cc2ad783fa59984d6760a10cbbf59f6d66ad" and "437174c1cced3338e08fa06f4376565950f2da65" have entirely different histories.
5a70cc2ad7
...
437174c1cc
13
.gitignore
vendored
13
.gitignore
vendored
@ -1,16 +1,11 @@
|
|||||||
# Dépendances
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
# NextJS
|
# NextJS
|
||||||
|
node_modules
|
||||||
.next
|
.next
|
||||||
|
|
||||||
# Environnement
|
# Cursor
|
||||||
.env.development
|
|
||||||
|
|
||||||
# IDE et éditeurs
|
|
||||||
.cursordirectory
|
.cursordirectory
|
||||||
.vscode
|
|
||||||
|
|
||||||
# Scripts de développement
|
# Dev
|
||||||
copy.sh
|
copy.sh
|
||||||
|
.env.development
|
||||||
start.sh
|
start.sh
|
||||||
@ -9,8 +9,6 @@
|
|||||||
git_dest: "/opt/Neah-Enkun"
|
git_dest: "/opt/Neah-Enkun"
|
||||||
git_branch: "master"
|
git_branch: "master"
|
||||||
traefik_service_name: "traefik"
|
traefik_service_name: "traefik"
|
||||||
packages:
|
|
||||||
- jq
|
|
||||||
docker_packages:
|
docker_packages:
|
||||||
- apt-transport-https
|
- apt-transport-https
|
||||||
- ca-certificates
|
- ca-certificates
|
||||||
@ -35,15 +33,6 @@
|
|||||||
delay: 5
|
delay: 5
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Installation de packages supplémentaires
|
|
||||||
apt:
|
|
||||||
name: "{{ packages }}"
|
|
||||||
state: present
|
|
||||||
register: pkg_status
|
|
||||||
until: pkg_status is success
|
|
||||||
retries: 3
|
|
||||||
delay: 5
|
|
||||||
|
|
||||||
- name: Installer les dépendances pour Docker
|
- name: Installer les dépendances pour Docker
|
||||||
apt:
|
apt:
|
||||||
name: "{{ docker_packages }}"
|
name: "{{ docker_packages }}"
|
||||||
|
|||||||
@ -33,16 +33,6 @@
|
|||||||
- account/view-profile
|
- account/view-profile
|
||||||
student_permissions:
|
student_permissions:
|
||||||
- master-realm/view-users
|
- master-realm/view-users
|
||||||
keycloak_client:
|
|
||||||
client_id: "front"
|
|
||||||
client_secret: "Klsbm7hzyXscypXU0wUPPVBrttFPt6Pn"
|
|
||||||
root_url: "http://neah.local/"
|
|
||||||
redirect_uris:
|
|
||||||
- "http://neah.local/*"
|
|
||||||
- "http://localhost:3000/*"
|
|
||||||
web_origins:
|
|
||||||
- "http://neah.local"
|
|
||||||
- "http://localhost:3000"
|
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Lancer le service Keycloak
|
- name: Lancer le service Keycloak
|
||||||
@ -140,69 +130,6 @@
|
|||||||
debug:
|
debug:
|
||||||
msg: "Erreur lors de l'attribution des permissions aux rôles"
|
msg: "Erreur lors de l'attribution des permissions aux rôles"
|
||||||
|
|
||||||
- name: Configurer le client front
|
|
||||||
block:
|
|
||||||
- name: Créer le client
|
|
||||||
shell: >
|
|
||||||
docker exec {{ keycloak_container }} {{ keycloak_bin }} create clients -r {{ keycloak_realm }}
|
|
||||||
-s clientId={{ keycloak_client.client_id }}
|
|
||||||
-s secret={{ keycloak_client.client_secret }}
|
|
||||||
-s protocol=openid-connect
|
|
||||||
-s publicClient=false
|
|
||||||
-s authorizationServicesEnabled=true
|
|
||||||
-s serviceAccountsEnabled=true
|
|
||||||
-s standardFlowEnabled=true
|
|
||||||
-s implicitFlowEnabled=true
|
|
||||||
-s directAccessGrantsEnabled=true
|
|
||||||
-s rootUrl={{ keycloak_client.root_url }}
|
|
||||||
-s baseUrl={{ keycloak_client.root_url }}
|
|
||||||
-s 'redirectUris=["{{ keycloak_client.redirect_uris | join('","') }}"]'
|
|
||||||
-s 'webOrigins=["{{ keycloak_client.web_origins | join('","') }}"]'
|
|
||||||
register: create_client
|
|
||||||
until: create_client is success
|
|
||||||
retries: 3
|
|
||||||
delay: 5
|
|
||||||
when: check_config.rc != 0
|
|
||||||
rescue:
|
|
||||||
- name: Gérer les erreurs de création du client
|
|
||||||
debug:
|
|
||||||
msg: "Erreur lors de la création du client front"
|
|
||||||
|
|
||||||
- name: Configurer le Client Scope Profile
|
|
||||||
block:
|
|
||||||
- name: Récupérer l'ID du scope profile
|
|
||||||
shell: |
|
|
||||||
ID=$(docker exec {{ keycloak_container }} {{ keycloak_bin }} get client-scopes -r {{ keycloak_realm }} --fields id,name --format json | jq -r '.[] | select(.name=="profile") | .id')
|
|
||||||
echo $ID
|
|
||||||
register: profile_scope_id
|
|
||||||
until: profile_scope_id.stdout != ""
|
|
||||||
retries: 3
|
|
||||||
delay: 5
|
|
||||||
|
|
||||||
- name: Ajouter le Mapper realm roles au scope profile
|
|
||||||
shell: >
|
|
||||||
docker exec {{ keycloak_container }} {{ keycloak_bin }} create client-scopes/{{ profile_scope_id.stdout | trim }}/protocol-mappers/models
|
|
||||||
-r {{ keycloak_realm }}
|
|
||||||
-s name="realm roles"
|
|
||||||
-s protocol="openid-connect"
|
|
||||||
-s protocolMapper="oidc-usermodel-realm-role-mapper"
|
|
||||||
-s 'config."id.token.claim"=true'
|
|
||||||
-s 'config."access.token.claim"=true'
|
|
||||||
-s 'config."userinfo.token.claim"=true'
|
|
||||||
-s 'config."claim.name"="realm_roles"'
|
|
||||||
-s 'config."introspection.token.claim"=true'
|
|
||||||
-s 'config."multivalued"=true'
|
|
||||||
register: create_mapper
|
|
||||||
until: create_mapper is success
|
|
||||||
retries: 3
|
|
||||||
delay: 5
|
|
||||||
when: profile_scope_id.stdout != ""
|
|
||||||
when: check_config.rc != 0
|
|
||||||
rescue:
|
|
||||||
- name: Gérer les erreurs de configuration du mapper
|
|
||||||
debug:
|
|
||||||
msg: "Erreur lors de la configuration du mapper realm roles"
|
|
||||||
|
|
||||||
- name: Supprimer l'administrateur temporaire
|
- name: Supprimer l'administrateur temporaire
|
||||||
block:
|
block:
|
||||||
- name: Récupérer les informations
|
- name: Récupérer les informations
|
||||||
|
|||||||
@ -11,37 +11,33 @@ export const authOptions: NextAuthOptions = {
|
|||||||
profile(profileData) {
|
profile(profileData) {
|
||||||
return {
|
return {
|
||||||
id: profileData.sub,
|
id: profileData.sub,
|
||||||
first_name: profileData.given_name,
|
name: profileData.name || profileData.preferred_username,
|
||||||
last_name: profileData.family_name,
|
|
||||||
username: profileData.preferred_username,
|
|
||||||
email: profileData.email,
|
email: profileData.email,
|
||||||
role: profileData.realm_roles,
|
image: null,
|
||||||
|
// Extraction du rôle ou groupe de l'utilisateur depuis Keycloak
|
||||||
|
role: Array.isArray(profileData.realm_access?.roles)
|
||||||
|
? profileData.realm_access.roles
|
||||||
|
: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
callbacks: {
|
callbacks: {
|
||||||
async jwt({ token, account, profile }) {
|
async jwt({ token, account, profile }) {
|
||||||
console.log("Token", token);
|
|
||||||
console.log("Account", account);
|
|
||||||
console.log("Profile", profile);
|
|
||||||
// Au moment de la première connexion, sauvegarde de l'access token et du rôle dans le JWT
|
// Au moment de la première connexion, sauvegarde de l'access token et du rôle dans le JWT
|
||||||
if (account && profile) {
|
if (account && profile) {
|
||||||
token.accessToken = account.access_token;
|
token.accessToken = account.access_token;
|
||||||
token.first_name = profile.given_name;
|
token.role = profile.role;
|
||||||
token.last_name = profile.family_name;
|
|
||||||
token.username = profile.preferred_username;
|
|
||||||
token.role = profile.realm_roles;
|
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
},
|
},
|
||||||
async session({ session, token }) {
|
async session({ session, token }) {
|
||||||
// On injecte l'access token et le rôle dans la session accessible côté client
|
// On injecte l'access token et le rôle dans la session accessible côté client
|
||||||
session.accessToken = token.accessToken as string;
|
session.accessToken = token.accessToken as string;
|
||||||
session.user.first_name = token.first_name as string;
|
session.user.role =
|
||||||
session.user.last_name = token.last_name as string;
|
typeof token.role == "string" || Array.isArray(token.role)
|
||||||
session.user.username = token.username as string;
|
? token.role
|
||||||
session.user.role = token.role as string[];
|
: [];
|
||||||
return session;
|
return session;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Calendar,
|
Calendar,
|
||||||
MessageSquare,
|
MessageSquare,
|
||||||
@ -17,8 +17,6 @@ export function MainNav() {
|
|||||||
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
|
|
||||||
console.log(session);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='flex items-center justify-between p-4 bg-black'>
|
<div className='flex items-center justify-between p-4 bg-black'>
|
||||||
@ -72,26 +70,14 @@ export function MainNav() {
|
|||||||
<Bell className='w-6 h-6' />
|
<Bell className='w-6 h-6' />
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
<div className='cursor-pointer text-white/80 hover:text-white'>
|
||||||
{session ? (
|
{session ? (
|
||||||
<div className='flex items-center space-x-4'>
|
<span>{session.user.name}</span>
|
||||||
<div className='cursor-pointer text-white/80 hover:text-white'>
|
|
||||||
<span>
|
|
||||||
{session.user.first_name} {session.user.last_name} -{" "}
|
|
||||||
{session.user.role.includes("admin") ? "Admin" : ""}
|
|
||||||
{session.user.role.includes("TEACHERS") ? "Teacher" : ""}
|
|
||||||
{session.user.role.includes("STUDENTS") ? "Student" : ""}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className='cursor-pointer text-white/80 hover:text-white'>
|
|
||||||
<Link href='/api/auth/signout'>Logout</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<div className='cursor-pointer text-white/80 hover:text-white'>
|
|
||||||
<Link href='/api/auth/signin'>Login</Link>
|
<Link href='/api/auth/signin'>Login</Link>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
|
<Sidebar isOpen={isSidebarOpen} onClose={() => setIsSidebarOpen(false)} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
14
front/types/next-auth.d.ts
vendored
14
front/types/next-auth.d.ts
vendored
@ -3,20 +3,13 @@ import NextAuth, { DefaultSession, DefaultUser } from "next-auth";
|
|||||||
declare module "next-auth" {
|
declare module "next-auth" {
|
||||||
interface Session {
|
interface Session {
|
||||||
user: {
|
user: {
|
||||||
first_name: string;
|
role?: string[] | string | null;
|
||||||
last_name: string;
|
|
||||||
email: string;
|
|
||||||
username: string;
|
|
||||||
role: string[];
|
|
||||||
} & DefaultSession["user"];
|
} & DefaultSession["user"];
|
||||||
accessToken?: string;
|
accessToken?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface JWT {
|
interface JWT {
|
||||||
accessToken?: string;
|
accessToken?: string;
|
||||||
first_name?: string;
|
|
||||||
last_name?: string;
|
|
||||||
username?: string;
|
|
||||||
role?: string[] | string | null;
|
role?: string[] | string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,9 +18,6 @@ declare module "next-auth" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Profile {
|
interface Profile {
|
||||||
given_name: string;
|
role?: string[] | string | null;
|
||||||
family_name: string;
|
|
||||||
preferred_username: string;
|
|
||||||
realm_roles: string[];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user