Added oidc connection
This commit is contained in:
@@ -11,3 +11,25 @@ And finaly we run `./gradlew bootRun`
|
|||||||
The compose file is enough.
|
The compose file is enough.
|
||||||
|
|
||||||
`launcher.sh` checks that the migrations are applied and then runs the spring boot server on port 8080
|
`launcher.sh` checks that the migrations are applied and then runs the spring boot server on port 8080
|
||||||
|
|
||||||
|
|
||||||
|
## OIDC
|
||||||
|
|
||||||
|
In order to connect to oidc, you need to setup the following options, if `bcom` is your provider name:
|
||||||
|
```Yaml
|
||||||
|
spring:
|
||||||
|
security:
|
||||||
|
oauth2:
|
||||||
|
client:
|
||||||
|
activate: true
|
||||||
|
registration:
|
||||||
|
bcom:
|
||||||
|
provider: bcom
|
||||||
|
client-id: misael
|
||||||
|
client-secret: "myclientsecret"
|
||||||
|
authorization-grant-type: authorization_code
|
||||||
|
scope: openid,roles
|
||||||
|
provider:
|
||||||
|
bcom:
|
||||||
|
issuer-uri: "https://auth.example.com/realms/bcom"
|
||||||
|
```
|
||||||
@@ -36,6 +36,7 @@ dependencies {
|
|||||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:_'
|
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:_'
|
||||||
implementation Spring.boot.web
|
implementation Spring.boot.web
|
||||||
implementation 'org.springframework:spring-jdbc:_'
|
implementation 'org.springframework:spring-jdbc:_'
|
||||||
|
implementation Spring.boot.oauth2Client
|
||||||
implementation 'org.flywaydb:flyway-core:_'
|
implementation 'org.flywaydb:flyway-core:_'
|
||||||
implementation 'org.flywaydb:flyway-database-postgresql:_'
|
implementation 'org.flywaydb:flyway-database-postgresql:_'
|
||||||
implementation Spring.session.jdbc
|
implementation Spring.session.jdbc
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ services:
|
|||||||
- 'POSTGRES_DB=misael'
|
- 'POSTGRES_DB=misael'
|
||||||
- 'POSTGRES_PASSWORD=misael-dev'
|
- 'POSTGRES_PASSWORD=misael-dev'
|
||||||
- 'POSTGRES_USER=misael'
|
- 'POSTGRES_USER=misael'
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
networks:
|
networks:
|
||||||
- misanetwork
|
- misanetwork
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
|
|
||||||
import com.bernard.misael.auth.repository.UserRepository;
|
import com.bernard.misael.auth.repository.UserRepository;
|
||||||
import com.bernard.misael.auth.service.UserService;
|
import com.bernard.misael.auth.service.UserService;
|
||||||
import com.bernard.misael.auth.model.Role;
|
import com.bernard.misael.auth.model.Privilege;
|
||||||
import com.bernard.misael.auth.model.User;
|
import com.bernard.misael.auth.model.User;
|
||||||
import com.bernard.misael.auth.service.dto.UserDto;
|
import com.bernard.misael.auth.service.dto.UserDto;
|
||||||
|
|
||||||
@@ -97,12 +97,14 @@ public class AuthController {
|
|||||||
@Getter
|
@Getter
|
||||||
public static class UserInfo implements Comparable<UserInfo> {
|
public static class UserInfo implements Comparable<UserInfo> {
|
||||||
private long id;
|
private long id;
|
||||||
|
private String oidcId;
|
||||||
private String pseudo;
|
private String pseudo;
|
||||||
private String roles;
|
private String roles;
|
||||||
public UserInfo(User u){
|
public UserInfo(User u){
|
||||||
this.id = u.getId();
|
this.id = u.getId();
|
||||||
|
this.oidcId = u.getOidcId();
|
||||||
this.pseudo = u.getName();
|
this.pseudo = u.getName();
|
||||||
this.roles = u.getRoles().stream().map(Role::getName).collect(Collectors.joining(";"));
|
this.roles = u.getPrivileges().stream().map(Privilege::name).collect(Collectors.joining(";"));
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(UserInfo other) {
|
public int compareTo(UserInfo other) {
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
package com.bernard.misael.auth;
|
package com.bernard.misael.auth;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.bernard.misael.auth.repository.UserRepository;
|
|
||||||
import com.bernard.misael.auth.model.Privilege;
|
|
||||||
import com.bernard.misael.auth.model.Role;
|
|
||||||
import com.bernard.misael.auth.model.User;
|
import com.bernard.misael.auth.model.User;
|
||||||
|
import com.bernard.misael.auth.repository.UserRepository;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class CustomUserDetailsService implements UserDetailsService {
|
public class CustomUserDetailsService implements UserDetailsService {
|
||||||
@@ -28,16 +22,9 @@ public class CustomUserDetailsService implements UserDetailsService {
|
|||||||
User user = userRepository.findByName(pseudo);
|
User user = userRepository.findByName(pseudo);
|
||||||
|
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
Stream<Privilege> inducedPrivileges = user.getRoles().stream()
|
|
||||||
.map(Role::getPrivileges)
|
|
||||||
.map(Set<Privilege>::stream)
|
|
||||||
.flatMap(Function.identity())
|
|
||||||
.sorted()
|
|
||||||
.distinct();
|
|
||||||
Stream<Role> roles = user.getRoles().stream();
|
|
||||||
return new org.springframework.security.core.userdetails.User(user.getName(),
|
return new org.springframework.security.core.userdetails.User(user.getName(),
|
||||||
user.getPassword(),
|
user.getPassword(),
|
||||||
Stream.concat(inducedPrivileges, roles).toList()
|
user.getPrivileges()
|
||||||
);
|
);
|
||||||
}else{
|
}else{
|
||||||
throw new UsernameNotFoundException("Invalid username or password.");
|
throw new UsernameNotFoundException("Invalid username or password.");
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import java.util.logging.Logger;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.env.Environment;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
@@ -12,9 +14,18 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
|
||||||
|
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
|
||||||
|
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||||
|
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
|
import com.bernard.misael.auth.model.User;
|
||||||
|
import com.bernard.misael.auth.service.UserService;
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@@ -23,8 +34,10 @@ public class SpringSecurity {
|
|||||||
|
|
||||||
public static final Logger LOG = Logger.getLogger(SpringSecurity.class.getName());
|
public static final Logger LOG = Logger.getLogger(SpringSecurity.class.getName());
|
||||||
|
|
||||||
@Autowired
|
public static final boolean oidcActivated(Environment env) {
|
||||||
private UserDetailsService userDetailsService;
|
String activate = env.getProperty("spring.security.oauth2.client.activate");
|
||||||
|
return (activate!=null) && activate.equalsIgnoreCase("true");
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public static PasswordEncoder passwordEncoder(){
|
public static PasswordEncoder passwordEncoder(){
|
||||||
@@ -32,29 +45,50 @@ public class SpringSecurity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http, Environment env, final UserService us) throws Exception {
|
||||||
http.csrf(csrf -> csrf.disable())
|
http.csrf(csrf -> csrf.disable());
|
||||||
.authorizeHttpRequests((authorize) ->
|
http.authorizeHttpRequests(authorize ->
|
||||||
authorize
|
authorize
|
||||||
.requestMatchers("/**").permitAll()
|
.requestMatchers("/**").permitAll()
|
||||||
).formLogin(
|
);
|
||||||
|
if(oidcActivated(env)) {
|
||||||
|
http.oauth2Login(oauth2 -> oauth2.
|
||||||
|
userInfoEndpoint(userInfo -> userInfo.
|
||||||
|
oidcUserService(this.oidcUserService(us))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
http.formLogin(
|
||||||
form -> form
|
form -> form
|
||||||
.loginPage("/login")
|
.loginPage("/login")
|
||||||
.loginProcessingUrl("/login")
|
.loginProcessingUrl("/login")
|
||||||
.defaultSuccessUrl("/")
|
.defaultSuccessUrl("/")
|
||||||
.permitAll()
|
.permitAll()
|
||||||
).logout(
|
);
|
||||||
|
http.logout(
|
||||||
logout -> logout
|
logout -> logout
|
||||||
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
|
||||||
.permitAll()
|
.permitAll()
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return http.build();
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
public void configureGlobal(AuthenticationManagerBuilder auth, UserDetailsService userDetailsService) throws Exception {
|
||||||
auth
|
auth
|
||||||
.userDetailsService(userDetailsService)
|
.userDetailsService(userDetailsService)
|
||||||
.passwordEncoder(passwordEncoder());
|
.passwordEncoder(passwordEncoder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService(UserService us) {
|
||||||
|
final OidcUserService delegate = new OidcUserService();
|
||||||
|
|
||||||
|
return userRequest -> {
|
||||||
|
// We create the original user
|
||||||
|
OidcUser oidcUser = delegate.loadUser(userRequest);
|
||||||
|
User u = us.ensureUser(oidcUser);
|
||||||
|
return new DefaultOidcUser(u.getPrivileges(), oidcUser.getIdToken());
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,26 @@
|
|||||||
package com.bernard.misael.auth.model;
|
package com.bernard.misael.auth.model;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
|
||||||
public enum Privilege implements GrantedAuthority {
|
public enum Privilege implements GrantedAuthority {
|
||||||
|
|
||||||
LIST_USERS,ADD_USERS,LIST_QUIZZ,CREATE_QUIZZ,VIEW_ALL_FORMS;
|
LIST_USERS,ADD_USERS,LIST_QUIZZ,CREATE_QUIZZ,VIEW_ALL_FORMS;
|
||||||
|
|
||||||
|
public static final Map<String,Privilege> oidcRoles = Map.of(
|
||||||
|
"misael-view-all-forms",VIEW_ALL_FORMS,
|
||||||
|
"misael-list-users",LIST_USERS,
|
||||||
|
"misael-create-quizz",CREATE_QUIZZ,
|
||||||
|
"misael-list-quizz", LIST_QUIZZ
|
||||||
|
);
|
||||||
@Override
|
@Override
|
||||||
public String getAuthority() {
|
public String getAuthority() {
|
||||||
return this.name();
|
return this.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final Privilege ofOidcString(String s) {
|
||||||
|
return oidcRoles.getOrDefault(s, null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
package com.bernard.misael.auth.model;
|
|
||||||
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.springframework.security.core.GrantedAuthority;
|
|
||||||
|
|
||||||
import jakarta.persistence.CollectionTable;
|
|
||||||
import jakarta.persistence.Column;
|
|
||||||
import jakarta.persistence.ElementCollection;
|
|
||||||
import jakarta.persistence.Entity;
|
|
||||||
import jakarta.persistence.EnumType;
|
|
||||||
import jakarta.persistence.Enumerated;
|
|
||||||
import jakarta.persistence.FetchType;
|
|
||||||
import jakarta.persistence.GeneratedValue;
|
|
||||||
import jakarta.persistence.GenerationType;
|
|
||||||
import jakarta.persistence.Id;
|
|
||||||
import jakarta.persistence.JoinColumn;
|
|
||||||
import jakarta.persistence.ManyToMany;
|
|
||||||
import jakarta.persistence.Table;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Entity
|
|
||||||
@Table(name="roles")
|
|
||||||
public class Role implements GrantedAuthority
|
|
||||||
{
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Column(nullable=false, unique=true)
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
@ManyToMany(mappedBy="roles")
|
|
||||||
private List<User> users;
|
|
||||||
|
|
||||||
@ElementCollection(fetch = FetchType.EAGER)
|
|
||||||
@Enumerated(EnumType.STRING)
|
|
||||||
@CollectionTable(name = "role_privileges"
|
|
||||||
, joinColumns = @JoinColumn(name = "id"))
|
|
||||||
@Column(name = "privileges", nullable = false)
|
|
||||||
private Set<Privilege> privileges;
|
|
||||||
|
|
||||||
public Role(String name){
|
|
||||||
super();
|
|
||||||
this.setName(name);
|
|
||||||
this.setPrivileges(EnumSet.noneOf(Privilege.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAuthority() {
|
|
||||||
return "ROLE_"+name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,20 @@
|
|||||||
package com.bernard.misael.auth.model;
|
package com.bernard.misael.auth.model;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.bernard.misael.quizz.model.Quizz;
|
import com.bernard.misael.quizz.model.Quizz;
|
||||||
|
|
||||||
import jakarta.persistence.CascadeType;
|
import jakarta.persistence.CollectionTable;
|
||||||
import jakarta.persistence.Column;
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.ElementCollection;
|
||||||
import jakarta.persistence.Entity;
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.EnumType;
|
||||||
|
import jakarta.persistence.Enumerated;
|
||||||
import jakarta.persistence.FetchType;
|
import jakarta.persistence.FetchType;
|
||||||
import jakarta.persistence.GeneratedValue;
|
import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.GenerationType;
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.JoinColumn;
|
import jakarta.persistence.JoinColumn;
|
||||||
import jakarta.persistence.JoinTable;
|
|
||||||
import jakarta.persistence.ManyToMany;
|
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -40,15 +39,18 @@ public class User
|
|||||||
@Column(nullable=false,unique = true)
|
@Column(nullable=false,unique = true)
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@Column(nullable=false)
|
@Column(nullable=true, unique = true)
|
||||||
|
private String oidcId;
|
||||||
|
|
||||||
|
@Column(nullable=true)
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
|
@ElementCollection(fetch = FetchType.EAGER)
|
||||||
@JoinTable(
|
@Enumerated(EnumType.STRING)
|
||||||
name="users_roles",
|
@CollectionTable(name = "user_privileges",
|
||||||
joinColumns={@JoinColumn(name="USER_ID", referencedColumnName="ID")},
|
joinColumns = @JoinColumn(name = "id"))
|
||||||
inverseJoinColumns={@JoinColumn(name="ROLE_ID", referencedColumnName="ID")})
|
@Column(name = "privileges", nullable = false)
|
||||||
private List<Role> roles = new ArrayList<>();
|
private Set<Privilege> privileges;
|
||||||
|
|
||||||
@OneToMany(mappedBy="owner")
|
@OneToMany(mappedBy="owner")
|
||||||
private Set<Quizz> myQuizzs;
|
private Set<Quizz> myQuizzs;
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
package com.bernard.misael.auth.repository;
|
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
|
||||||
|
|
||||||
import com.bernard.misael.auth.model.Role;
|
|
||||||
|
|
||||||
public interface RoleRepository extends JpaRepository<Role, Long> {
|
|
||||||
|
|
||||||
Role findByName(String name);
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.bernard.misael.auth.repository;
|
package com.bernard.misael.auth.repository;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
import com.bernard.misael.auth.model.User;
|
import com.bernard.misael.auth.model.User;
|
||||||
@@ -7,5 +9,6 @@ import com.bernard.misael.auth.model.User;
|
|||||||
public interface UserRepository extends JpaRepository<User, Long> {
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
|
|
||||||
User findByName(String pseudo);
|
User findByName(String pseudo);
|
||||||
|
Optional<User> findByOidcId(String oidcId);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.bernard.misael.auth.service;
|
package com.bernard.misael.auth.service;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Set;
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -11,11 +10,9 @@ import org.springframework.lang.NonNull;
|
|||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import com.bernard.misael.auth.repository.RoleRepository;
|
|
||||||
import com.bernard.misael.auth.repository.UserRepository;
|
|
||||||
import com.bernard.misael.auth.model.Privilege;
|
import com.bernard.misael.auth.model.Privilege;
|
||||||
import com.bernard.misael.auth.model.Role;
|
|
||||||
import com.bernard.misael.auth.model.User;
|
import com.bernard.misael.auth.model.User;
|
||||||
|
import com.bernard.misael.auth.repository.UserRepository;
|
||||||
|
|
||||||
import jakarta.transaction.Transactional;
|
import jakarta.transaction.Transactional;
|
||||||
|
|
||||||
@@ -28,9 +25,6 @@ public class AdminMaker implements
|
|||||||
@Autowired
|
@Autowired
|
||||||
private UserRepository userRepository;
|
private UserRepository userRepository;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private RoleRepository roleRepository;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private PasswordEncoder passwordEncoder;
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
@@ -38,37 +32,21 @@ public class AdminMaker implements
|
|||||||
@Transactional
|
@Transactional
|
||||||
public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
|
public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
|
||||||
|
|
||||||
if (alreadySetup)
|
if (alreadySetup) return;
|
||||||
return;
|
|
||||||
Logger log = Logger.getLogger("AdminMaker");
|
Logger log = Logger.getLogger("AdminMaker");
|
||||||
log.info("Checking that privileges and mysaa user exist");
|
log.info("Checking that privileges and mysaa user exist");
|
||||||
|
|
||||||
Role adminRole = createRoleIfNotFound("ADMIN", EnumSet.allOf(Privilege.class));
|
|
||||||
createRoleIfNotFound("USER", EnumSet.noneOf(Privilege.class));
|
|
||||||
|
|
||||||
User mysaa = userRepository.findByName("mysaa");
|
User mysaa = userRepository.findByName("mysaa");
|
||||||
if (mysaa == null) {
|
if (mysaa == null) {
|
||||||
User user = new User();
|
User user = new User();
|
||||||
user.setName("mysaa");
|
user.setName("mysaa");
|
||||||
user.setPassword(passwordEncoder.encode("super"));
|
user.setPassword(passwordEncoder.encode("super"));
|
||||||
user.setRoles(Arrays.asList(adminRole));
|
user.setPrivileges(Set.of(Privilege.values()));
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
alreadySetup = true;
|
alreadySetup = true;
|
||||||
log.info("Everything needed has been created");
|
log.info("Everything needed has been created");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
private Role createRoleIfNotFound(
|
|
||||||
String name, EnumSet<Privilege> privileges) {
|
|
||||||
|
|
||||||
Role role = roleRepository.findByName(name);
|
|
||||||
if (role == null) {
|
|
||||||
role = new Role(name);
|
|
||||||
role.setPrivileges(privileges);
|
|
||||||
roleRepository.save(role);
|
|
||||||
}
|
|
||||||
return role;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,20 @@
|
|||||||
package com.bernard.misael.auth.service;
|
package com.bernard.misael.auth.service;
|
||||||
|
|
||||||
|
import java.security.Principal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||||
|
|
||||||
import com.bernard.misael.auth.model.Privilege;
|
import com.bernard.misael.auth.model.Privilege;
|
||||||
import com.bernard.misael.auth.model.User;
|
import com.bernard.misael.auth.model.User;
|
||||||
import com.bernard.misael.auth.service.dto.UserDto;
|
import com.bernard.misael.auth.service.dto.UserDto;
|
||||||
|
|
||||||
public interface UserService {
|
public interface UserService {
|
||||||
|
|
||||||
|
User ofPrincipal(Principal p);
|
||||||
|
|
||||||
|
User ensureUser(OidcUser user);
|
||||||
|
|
||||||
void saveUser(UserDto userDto);
|
void saveUser(UserDto userDto);
|
||||||
void changePassword(User user, String password);
|
void changePassword(User user, String password);
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,22 @@
|
|||||||
package com.bernard.misael.auth.service;
|
package com.bernard.misael.auth.service;
|
||||||
|
import java.security.Principal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.bernard.misael.auth.repository.UserRepository;
|
import com.bernard.misael.auth.repository.UserRepository;
|
||||||
import com.bernard.misael.auth.service.dto.UserDto;
|
import com.bernard.misael.auth.service.dto.UserDto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
import com.bernard.misael.auth.model.Privilege;
|
import com.bernard.misael.auth.model.Privilege;
|
||||||
import com.bernard.misael.auth.model.User;
|
import com.bernard.misael.auth.model.User;
|
||||||
|
|
||||||
@@ -22,6 +32,51 @@ public class UserServiceImpl implements UserService {
|
|||||||
this.passwordEncoder = passwordEncoder;
|
this.passwordEncoder = passwordEncoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public User ensureUser(OidcUser oidcUser) {
|
||||||
|
String username = oidcUser.getPreferredUsername();
|
||||||
|
String id = oidcUser.getName();
|
||||||
|
Set<Privilege> privileges;
|
||||||
|
try {
|
||||||
|
privileges = oidcUser
|
||||||
|
.<Map<String,Map<String,List<String>>>>getAttribute("resource_access")
|
||||||
|
.getOrDefault("misael",Map.of())
|
||||||
|
.getOrDefault("roles",List.of())
|
||||||
|
.stream()
|
||||||
|
.map(Privilege::ofOidcString)
|
||||||
|
.filter(p -> p != null)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<User> u = userRepository.findByOidcId(id);
|
||||||
|
if(u.isEmpty()) {
|
||||||
|
Optional<User> uN = Optional.ofNullable(userRepository.findByName(username));
|
||||||
|
if(uN.isEmpty()) {
|
||||||
|
User u0 = new User();
|
||||||
|
u0.setOidcId(id);
|
||||||
|
u0.setName(username);
|
||||||
|
userRepository.save(u0);
|
||||||
|
u = Optional.of(u0);
|
||||||
|
} else {
|
||||||
|
User u0 = uN.get();
|
||||||
|
u0.setOidcId(id);
|
||||||
|
userRepository.save(u0);
|
||||||
|
u = uN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
User theu = u.get();
|
||||||
|
if(!theu.getPrivileges().equals(privileges)) {
|
||||||
|
theu.setPrivileges(privileges);
|
||||||
|
userRepository.save(theu);
|
||||||
|
}
|
||||||
|
return theu;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveUser(UserDto userDto) {
|
public void saveUser(UserDto userDto) {
|
||||||
User user = new User();
|
User user = new User();
|
||||||
@@ -29,7 +84,7 @@ public class UserServiceImpl implements UserService {
|
|||||||
// encrypt the password using spring security
|
// encrypt the password using spring security
|
||||||
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
|
user.setPassword(passwordEncoder.encode(userDto.getPassword()));
|
||||||
|
|
||||||
user.setRoles(List.of());
|
user.setPrivileges(Set.of());
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@@ -58,7 +113,22 @@ public class UserServiceImpl implements UserService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasPrivilege(User u, Privilege p) {
|
public boolean hasPrivilege(User u, Privilege p) {
|
||||||
//TODO faire une query sql propre avec ça
|
return u.getPrivileges().contains(p);
|
||||||
return u.getRoles().stream().anyMatch(r -> r.getPrivileges().contains(p));
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public User ofPrincipal(Principal p) {
|
||||||
|
User u = null;
|
||||||
|
if(p instanceof OAuth2AuthenticationToken) {
|
||||||
|
OAuth2AuthenticationToken o = (OAuth2AuthenticationToken) p;
|
||||||
|
u = userRepository.findByOidcId(o.getName()).orElseThrow(() -> new RuntimeException("Oauth2 user was not in the database"));
|
||||||
|
}
|
||||||
|
if(p instanceof UsernamePasswordAuthenticationToken) {
|
||||||
|
UsernamePasswordAuthenticationToken o = (UsernamePasswordAuthenticationToken) p;
|
||||||
|
u = userRepository.findByName(o.getName());
|
||||||
|
}
|
||||||
|
return u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ import org.springframework.stereotype.Controller;
|
|||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
import com.bernard.misael.auth.repository.UserRepository;
|
import com.bernard.misael.auth.service.UserService;
|
||||||
import com.bernard.misael.quizz.model.Quizz;
|
import com.bernard.misael.quizz.model.Quizz;
|
||||||
import com.bernard.misael.quizz.model.QuizzForm;
|
import com.bernard.misael.quizz.model.QuizzForm;
|
||||||
import com.bernard.misael.auth.model.User;
|
import com.bernard.misael.auth.model.User;
|
||||||
@@ -32,15 +32,12 @@ import org.springframework.web.bind.annotation.PathVariable;
|
|||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/questions")
|
@RequestMapping("/questions")
|
||||||
public class QuestionsController {
|
public class QuestionsController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
UserRepository ur;
|
UserService us;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
QuizzManager qm;
|
QuizzManager qm;
|
||||||
@@ -56,14 +53,11 @@ public class QuestionsController {
|
|||||||
*/
|
*/
|
||||||
@GetMapping("/quizz")
|
@GetMapping("/quizz")
|
||||||
public String getQuizz(Model model, Principal p) {
|
public String getQuizz(Model model, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u!=null) {
|
if(u!=null) {
|
||||||
model.addAttribute("answerableQuizz",qm.answerableQuizz(u));
|
model.addAttribute("answerableQuizz",qm.answerableQuizz(u));
|
||||||
model.addAttribute("editableQuizz",qm.editableQuizz(u));
|
model.addAttribute("editableQuizz",qm.editableQuizz(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
return "quizz.html";
|
return "quizz.html";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,9 +66,7 @@ public class QuestionsController {
|
|||||||
*/
|
*/
|
||||||
@GetMapping("/forms")
|
@GetMapping("/forms")
|
||||||
public String getForms(Model model, Principal p) {
|
public String getForms(Model model, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u!=null) {
|
if(u!=null) {
|
||||||
model.addAttribute("finishedForms",qfrepo.findByUserAndDoneTrue(u));
|
model.addAttribute("finishedForms",qfrepo.findByUserAndDoneTrue(u));
|
||||||
model.addAttribute("openForms",qfrepo.findByUserAndDoneFalse(u));
|
model.addAttribute("openForms",qfrepo.findByUserAndDoneFalse(u));
|
||||||
@@ -88,9 +80,7 @@ public class QuestionsController {
|
|||||||
*/
|
*/
|
||||||
@GetMapping("/showform/{id}")
|
@GetMapping("/showform/{id}")
|
||||||
public Object showForm(@PathVariable("id") long id, Model m, Principal p) {
|
public Object showForm(@PathVariable("id") long id, Model m, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return "redirect:/login?restricted";
|
return "redirect:/login?restricted";
|
||||||
Optional<QuizzForm> oqf = qm.canViewQuizzForm(u, id);
|
Optional<QuizzForm> oqf = qm.canViewQuizzForm(u, id);
|
||||||
@@ -107,9 +97,7 @@ public class QuestionsController {
|
|||||||
*/
|
*/
|
||||||
@GetMapping("/showformsadvancements/{id}")
|
@GetMapping("/showformsadvancements/{id}")
|
||||||
public Object showFormsAdvancements(@PathVariable("id") long id, Model m, Principal p) {
|
public Object showFormsAdvancements(@PathVariable("id") long id, Model m, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return "redirect:/login?restricted";
|
return "redirect:/login?restricted";
|
||||||
Optional<Quizz> oq = qm.canViewQuizzFormsOfQuizz(u, id);
|
Optional<Quizz> oq = qm.canViewQuizzFormsOfQuizz(u, id);
|
||||||
@@ -126,9 +114,7 @@ public class QuestionsController {
|
|||||||
*/
|
*/
|
||||||
@PostMapping("/getformdata/{id}")
|
@PostMapping("/getformdata/{id}")
|
||||||
public Object showFormApi(@PathVariable("id") long id, Principal p) {
|
public Object showFormApi(@PathVariable("id") long id, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return "redirect:/login?restricted";
|
return "redirect:/login?restricted";
|
||||||
JsonNode out = qm.getQuizzFormData(u, id);
|
JsonNode out = qm.getQuizzFormData(u, id);
|
||||||
@@ -140,9 +126,7 @@ public class QuestionsController {
|
|||||||
*/
|
*/
|
||||||
@GetMapping("/getallformsdata/{id}")
|
@GetMapping("/getallformsdata/{id}")
|
||||||
public Object getAllFormsData(@PathVariable("id") long id, Principal p) {
|
public Object getAllFormsData(@PathVariable("id") long id, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return "redirect:/login?restricted";
|
return "redirect:/login?restricted";
|
||||||
JsonNode out = qm.getAllFormsData(u, id);
|
JsonNode out = qm.getAllFormsData(u, id);
|
||||||
@@ -154,9 +138,7 @@ public class QuestionsController {
|
|||||||
*/
|
*/
|
||||||
@PostMapping("/getformadvancements/{id}")
|
@PostMapping("/getformadvancements/{id}")
|
||||||
public Object showFormAdvancements(@PathVariable("id") long id, Principal p) {
|
public Object showFormAdvancements(@PathVariable("id") long id, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return "redirect:/login?restricted";
|
return "redirect:/login?restricted";
|
||||||
JsonNode out = qm.getQuizzFormAdvancments(u, id);
|
JsonNode out = qm.getQuizzFormAdvancments(u, id);
|
||||||
@@ -168,9 +150,7 @@ public class QuestionsController {
|
|||||||
*/
|
*/
|
||||||
@GetMapping("/duplicate-quizz/{id}")
|
@GetMapping("/duplicate-quizz/{id}")
|
||||||
public Object duplicateQuizz(@PathVariable("id") long id, Principal p) {
|
public Object duplicateQuizz(@PathVariable("id") long id, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return "redirect:/login?restricted";
|
return "redirect:/login?restricted";
|
||||||
Quizz q = qm.duplicateQuizz(u, id);
|
Quizz q = qm.duplicateQuizz(u, id);
|
||||||
@@ -181,7 +161,8 @@ public class QuestionsController {
|
|||||||
|
|
||||||
@GetMapping("/form/{q}")
|
@GetMapping("/form/{q}")
|
||||||
public String formpage(@PathVariable("q") long quizzId, Principal p, Model m) {
|
public String formpage(@PathVariable("q") long quizzId, Principal p, Model m) {
|
||||||
if (p==null)
|
User u = us.ofPrincipal(p);
|
||||||
|
if (u==null)
|
||||||
return "redirect:/login?restricted";
|
return "redirect:/login?restricted";
|
||||||
m.addAttribute("formid", quizzId);
|
m.addAttribute("formid", quizzId);
|
||||||
Quizz q = qrepo.getReferenceById(quizzId);
|
Quizz q = qrepo.getReferenceById(quizzId);
|
||||||
@@ -192,9 +173,7 @@ public class QuestionsController {
|
|||||||
|
|
||||||
@GetMapping("/question/{q}")
|
@GetMapping("/question/{q}")
|
||||||
public ResponseEntity<JsonNode> question(@PathVariable("q") long quizzId, Principal p) {
|
public ResponseEntity<JsonNode> question(@PathVariable("q") long quizzId, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
||||||
JsonNode out = qm.next(u, quizzId);
|
JsonNode out = qm.next(u, quizzId);
|
||||||
@@ -203,9 +182,7 @@ public class QuestionsController {
|
|||||||
|
|
||||||
@PostMapping("/answer/{q}")
|
@PostMapping("/answer/{q}")
|
||||||
public ResponseEntity<JsonNode> answer(@PathVariable("q") long quizzId, @RequestBody JsonNode data, Principal p) {
|
public ResponseEntity<JsonNode> answer(@PathVariable("q") long quizzId, @RequestBody JsonNode data, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
JsonNode out = qm.answer(u, quizzId, data);
|
JsonNode out = qm.answer(u, quizzId, data);
|
||||||
return new ResponseEntity<>(out, HttpStatus.OK);
|
return new ResponseEntity<>(out, HttpStatus.OK);
|
||||||
}
|
}
|
||||||
@@ -213,9 +190,7 @@ public class QuestionsController {
|
|||||||
@GetMapping("/new-quizz")
|
@GetMapping("/new-quizz")
|
||||||
@Secured("CREATE_QUIZZ")
|
@Secured("CREATE_QUIZZ")
|
||||||
public Object newQuizz(Principal p, Model m) {
|
public Object newQuizz(Principal p, Model m) {
|
||||||
if (p==null)
|
User u = us.ofPrincipal(p);
|
||||||
return "redirect:/login?restricted";
|
|
||||||
User u = ur.findByName(p.getName());
|
|
||||||
if (u==null)
|
if (u==null)
|
||||||
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
|
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
|
||||||
Quizz q = qm.newQuizz(u);
|
Quizz q = qm.newQuizz(u);
|
||||||
@@ -226,9 +201,7 @@ public class QuestionsController {
|
|||||||
Logger logger = LoggerFactory.getLogger(QuestionsController.class);
|
Logger logger = LoggerFactory.getLogger(QuestionsController.class);
|
||||||
@GetMapping("/quizz-edit/{q}")
|
@GetMapping("/quizz-edit/{q}")
|
||||||
public Object quizzEdit(@PathVariable("q") long quizzId, Principal p, Model m) {
|
public Object quizzEdit(@PathVariable("q") long quizzId, Principal p, Model m) {
|
||||||
if (p==null)
|
User u = us.ofPrincipal(p);
|
||||||
return "redirect:/login?restricted";
|
|
||||||
User u = ur.findByName(p.getName());
|
|
||||||
if (u==null || !qm.canEditQuizz(u, quizzId))
|
if (u==null || !qm.canEditQuizz(u, quizzId))
|
||||||
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
|
return new ResponseEntity<>(HttpStatus.FORBIDDEN);
|
||||||
m.addAttribute("quizzId", quizzId);
|
m.addAttribute("quizzId", quizzId);
|
||||||
@@ -238,9 +211,7 @@ public class QuestionsController {
|
|||||||
|
|
||||||
@PostMapping("/quizz-edit/{q}/get")
|
@PostMapping("/quizz-edit/{q}/get")
|
||||||
public ResponseEntity<JsonNode> quizzSetName(@PathVariable("q") long quizzId, Principal p) {
|
public ResponseEntity<JsonNode> quizzSetName(@PathVariable("q") long quizzId, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
||||||
JsonNode out = qm.getQuizzInfo(u, quizzId);
|
JsonNode out = qm.getQuizzInfo(u, quizzId);
|
||||||
@@ -249,9 +220,7 @@ public class QuestionsController {
|
|||||||
|
|
||||||
@PostMapping("/quizz-edit/{q}/set-name")
|
@PostMapping("/quizz-edit/{q}/set-name")
|
||||||
public ResponseEntity<JsonNode> quizzSetName(@PathVariable("q") long quizzId, @RequestBody String data, Principal p) {
|
public ResponseEntity<JsonNode> quizzSetName(@PathVariable("q") long quizzId, @RequestBody String data, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
||||||
JsonNode out = qm.setQuizzName(u, quizzId, data);
|
JsonNode out = qm.setQuizzName(u, quizzId, data);
|
||||||
@@ -260,9 +229,7 @@ public class QuestionsController {
|
|||||||
|
|
||||||
@PostMapping("/quizz-edit/{q}/add-question")
|
@PostMapping("/quizz-edit/{q}/add-question")
|
||||||
public ResponseEntity<JsonNode> quizzAddQuestion(@PathVariable("q") long quizzId, Principal p) {
|
public ResponseEntity<JsonNode> quizzAddQuestion(@PathVariable("q") long quizzId, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
||||||
JsonNode out = qm.addQuestion(u, quizzId);
|
JsonNode out = qm.addQuestion(u, quizzId);
|
||||||
@@ -271,9 +238,7 @@ public class QuestionsController {
|
|||||||
|
|
||||||
@PostMapping("/quizz-edit/{q}/remove-question/{qi}")
|
@PostMapping("/quizz-edit/{q}/remove-question/{qi}")
|
||||||
public ResponseEntity<JsonNode> quizzSetName(@PathVariable("q") long quizzId, @PathVariable("qi") long questionId, Principal p) {
|
public ResponseEntity<JsonNode> quizzSetName(@PathVariable("q") long quizzId, @PathVariable("qi") long questionId, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
||||||
JsonNode out = qm.removeQuestion(u, quizzId, questionId);
|
JsonNode out = qm.removeQuestion(u, quizzId, questionId);
|
||||||
@@ -282,9 +247,7 @@ public class QuestionsController {
|
|||||||
|
|
||||||
@PostMapping("/quizz-edit/{q}/reorder-questions")
|
@PostMapping("/quizz-edit/{q}/reorder-questions")
|
||||||
public ResponseEntity<JsonNode> quizzReorderQuestions(@PathVariable("q") long quizzId, @RequestBody JsonNode data, Principal p) {
|
public ResponseEntity<JsonNode> quizzReorderQuestions(@PathVariable("q") long quizzId, @RequestBody JsonNode data, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
||||||
if(!data.isArray())
|
if(!data.isArray())
|
||||||
@@ -306,9 +269,7 @@ public class QuestionsController {
|
|||||||
@PostMapping("/quizz-edit/{q}/edit-question/{qi}")
|
@PostMapping("/quizz-edit/{q}/edit-question/{qi}")
|
||||||
public ResponseEntity<JsonNode> quizzEditQuestion(@PathVariable("q") long quizzId,
|
public ResponseEntity<JsonNode> quizzEditQuestion(@PathVariable("q") long quizzId,
|
||||||
@PathVariable("qi") long questionId, @RequestBody JsonNode data, Principal p) {
|
@PathVariable("qi") long questionId, @RequestBody JsonNode data, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
||||||
|
|
||||||
@@ -319,9 +280,7 @@ public class QuestionsController {
|
|||||||
@PostMapping("/quizz-edit/{q}/set-question-type/{qi}")
|
@PostMapping("/quizz-edit/{q}/set-question-type/{qi}")
|
||||||
public ResponseEntity<JsonNode> quizzSetQuestionType(@PathVariable("q") long quizzId,
|
public ResponseEntity<JsonNode> quizzSetQuestionType(@PathVariable("q") long quizzId,
|
||||||
@PathVariable("qi") long questionId, @RequestBody JsonNode data, Principal p) {
|
@PathVariable("qi") long questionId, @RequestBody JsonNode data, Principal p) {
|
||||||
User u = null;
|
User u = us.ofPrincipal(p);
|
||||||
if (p!=null)
|
|
||||||
u = ur.findByName(p.getName());
|
|
||||||
if(u==null)
|
if(u==null)
|
||||||
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>(JsonNodeFactory.instance.objectNode(),HttpStatus.UNAUTHORIZED);
|
||||||
if(!data.isTextual())
|
if(!data.isTextual())
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
create table user_privileges (id bigint not null, privileges varchar(255) not null check (privileges in ('LIST_USERS','ADD_USERS','LIST_QUIZZ','CREATE_QUIZZ','VIEW_ALL_FORMS')), primary key (id, privileges));
|
||||||
|
drop table role_privileges cascade;
|
||||||
|
drop table roles cascade;
|
||||||
|
alter table if exists users alter column password drop not null;
|
||||||
|
alter table if exists users add column oidc_id varchar(255);
|
||||||
|
alter table if exists users drop constraint if exists UKs3fyv3dn1pq639igamsrq5vhj;
|
||||||
|
alter table if exists users add constraint UKs3fyv3dn1pq639igamsrq5vhj unique (oidc_id);
|
||||||
|
alter table if exists user_privileges add constraint FKqltalsck5q21fw7vcpsriacst foreign key (id) references users;
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<nav>
|
<nav>
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<div class="logo"><a href="/">Misael</a></div>
|
<div class="logo"><a href="/">Misael</a></div>
|
||||||
<div class="welcome" sec:authorize="isAuthenticated()">Logged in as <span sec:authentication="name"/></div>
|
|
||||||
<ul class="menu">
|
<ul class="menu">
|
||||||
<li><a href="/questions/quizz">Quizz</a></li>
|
<li><a href="/questions/quizz">Quizz</a></li>
|
||||||
<li><a href="/questions/forms">Forms</a></li>
|
<li><a href="/questions/forms">Forms</a></li>
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ version.org.springframework..spring-jdbc=6.2.3
|
|||||||
|
|
||||||
version.org.springframework.boot..spring-boot-docker-compose=3.4.3
|
version.org.springframework.boot..spring-boot-docker-compose=3.4.3
|
||||||
|
|
||||||
|
version.org.springframework.boot..spring-boot-starter-oauth2-client=4.1.0
|
||||||
|
|
||||||
version.org.webjars..jquery=1.9.1
|
version.org.webjars..jquery=1.9.1
|
||||||
## # available=1.10.1
|
## # available=1.10.1
|
||||||
## # available=1.10.2
|
## # available=1.10.2
|
||||||
|
|||||||
Reference in New Issue
Block a user