[DEV] some back upgrade and add password change (no return GUI)

This commit is contained in:
Edouard DUPIN 2023-01-05 00:13:10 +01:00
parent ca8274295e
commit f3ae1fcd1c
12 changed files with 140 additions and 85 deletions

View File

@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.kar</groupId>
<artifactId>karso</artifactId>
<version>0.1.0</version>
<version>0.2.0</version>
<properties>
<!--
<jaxb.version>2.3.1</jaxb.version>
@ -27,7 +27,7 @@
<dependency>
<groupId>kangaroo-and-rabbit</groupId>
<artifactId>archidata</artifactId>
<version>0.2.1</version>
<version>0.2.2</version>
</dependency>
<!-- testing -->
<dependency>

View File

@ -72,6 +72,7 @@ public class WebLauncher {
rc.register(SystemExceptionCatcher.class);
rc.register(FailExceptionCatcher.class);
rc.register(ExceptionCatcher.class);
// add default resource:
rc.registerClasses(UserResource.class);
rc.registerClasses(PublicKeyResource.class);

View File

@ -55,9 +55,6 @@ public class ApplicationResource {
@Path("get_token")
@RolesAllowed(value= {"USER", "ADMIN"})
public Response getClientToken(@Context SecurityContext sc, @QueryParam("application") String application) {
System.out.println("=====================================");
System.out.println("Get client Token()");
System.out.println("=====================================");
GenericContext gc = (GenericContext) sc.getUserPrincipal();
System.out.println("== USER ? " + gc.user);

View File

@ -1,19 +1,15 @@
package org.kar.karso.api;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.filter.GenericContext;
import org.kar.karso.model.*;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.kar.archidata.util.JWTWrapper;
import org.kar.archidata.annotation.security.PermitAll;
import org.kar.archidata.annotation.security.RolesAllowed;
import org.kar.archidata.exception.NotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.ws.rs.*;
@ -23,46 +19,46 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
@Path("/system_config")
@Produces( MediaType.APPLICATION_JSON)
public class SystemConfigResource {
public static class GetSignUpAvaillable {
public boolean signup;
public GetSignUpAvaillable(boolean availlable) {
this.signup = availlable;
}
public GetSignUpAvaillable() {
signup = false;
}
}
public SystemConfigResource() {
}
@GET
@Path("is_sign_up_availlable")
@PermitAll
public Response isSignUpAvaillable() {
Settings set = null;
try {
set = SqlWrapper.getWhere(Settings.class, "key", "=", "SIGN_UP_ENABLE");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
String result = "SERVER Internal error";
System.out.println(" result: " + result);
return Response.status(500).entity(result).build();
public GetSignUpAvaillable isSignUpAvaillable() throws Exception {
Settings set = SqlWrapper.getWhere(Settings.class, "key", "=", "SIGN_UP_ENABLE", false);
if (set == null) {
throw new NotFoundException("Value does not exist");
}
System.out.println(" get data: " + set);
boolean availlable = "true".equalsIgnoreCase(set.value);
return Response.status(200).entity("{ \"signup\":" + availlable + "}").build();
GetSignUpAvaillable tmp = new GetSignUpAvaillable(availlable);
System.out.println("mlkmlk " + tmp.signup);
return tmp;
}
@GET
@Path("key/{key}")
@RolesAllowed(value= {"USER", "ADMIN"})
public Response getKey(@Context SecurityContext sc, @PathParam("key") String key) {
Settings set = null;
try {
set = SqlWrapper.getWhere(Settings.class, "key", "=", key);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
String result = "Can not find the Key";
return Response.status(404).entity(result).build();
public Response getKey(@Context SecurityContext sc, @PathParam("key") String key) throws Exception {
Settings set = SqlWrapper.getWhere(Settings.class, "key", "=", key, false);
if (set == null) {
throw new NotFoundException("Value does not exist");
}
if (set.type.equals("BOOLEAN")) {
boolean availlable = "true".equalsIgnoreCase(set.value);
@ -81,7 +77,7 @@ public class SystemConfigResource {
public Response setKey(@Context SecurityContext sc, @PathParam("key") String key, String jsonRequest) throws Exception {
Settings res = null;
try {
res = SqlWrapper.getWhere(Settings.class, "key", "=", key);
res = SqlWrapper.getWhere(Settings.class, "key", "=", key, false);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
@ -95,7 +91,7 @@ public class SystemConfigResource {
res.value = value.asText();
SqlWrapper.update(res, res.id, Arrays.asList("value"));
SqlWrapper.update(res, res.id, List.of("value"));
return Response.status(201).entity("{ \"value\":\"" + res.value + "\"}").build();
}

View File

@ -2,10 +2,8 @@ package org.kar.karso.api;
import org.kar.archidata.model.GetToken;
import org.kar.archidata.model.User;
import org.kar.archidata.GlobalConfiguration;
import org.kar.archidata.SqlWrapper;
import org.kar.archidata.WhereCondition;
import org.kar.archidata.db.DBEntry;
import org.kar.archidata.exception.FailException;
import org.kar.archidata.exception.InputException;
import org.kar.archidata.exception.SystemException;
@ -22,10 +20,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
@ -38,14 +32,12 @@ public class UserResource {
public UserResource() {
}
// curl http://localhost:9993/api/users
@GET
@RolesAllowed("ADMIN")
public List<UserAuth> getUsers() throws Exception {
return SqlWrapper.gets(UserAuth.class, false);
}
// curl http://localhost:9993/api/users/3
@GET
@Path("{id}")
@RolesAllowed("ADMIN")
@ -102,29 +94,19 @@ public class UserResource {
if(data == null) {
throw new InputException("data", "No data set...");
}
if(data.password == null) {
throw new InputException("password", "null password");
if(data.newPassword == null || data.newPassword.length() != 128) {
throw new InputException("newPassword", "null password, or wrong hash size");
}
if(data.password.length() != 128) {
throw new InputException("password", "password has not the correct hash size");
}
// TODO: check every char are in the range 0-9a-f
// with security level 1: (No e-mail system)
UserAuth user = SqlWrapper.get(UserAuth.class, gc.user.id);
UserAuth user = checkAuthUser(data.method, data.login, data.time, data.password);
if (user == null) {
throw new SystemException("Fail to retrieve the user... (impossible case)");
}
user.password = data.password;
SqlWrapper.update(user, gc.user.id, List.of("password"));
// Process the update:
user.password = data.newPassword;
SqlWrapper.update(user, user.id, List.of("password"));
return Response.status(Response.Status.OK).build();
// With security level 2:
// TODO: Set the new password in the passwordChange
// TODO: set a uniqueID in the correct passwordValidation zone
// TODO: Set the data in the BDD
// TODO: send an e-mail
}
/*
@GET
@Path("validipass")
@ -156,6 +138,7 @@ public class UserResource {
return Response.status(404).build();
}
// TODO: add an application TOKEN and permit only 50 requested (maybe add an option to disable it).
@GET
@Path("/check_email")
@PermitAll
@ -170,46 +153,53 @@ public class UserResource {
return Response.status(404).build();
}
@POST
@Path("/get_token")
@PermitAll
@Consumes(MediaType.APPLICATION_JSON)
public GetToken getToken(DataGetToken data) throws Exception {
System.out.println("login: " + data.login );
private UserAuth checkAuthUser(String method, String login, String time, String password) throws Exception {
// check good version:
if (!data.method.contentEquals("v1")) {
throw new InputException("method", "Authentiocate-method-error (wrong version: '" + data.method + "')");
if (!"v1".contentEquals(method)) {
throw new InputException("method", "Authentiocate-method-error (wrong version: '" + method + "')");
}
// verify login or email is correct:
if (data.login.length() < 6) {
throw new InputException("login", "Authentiocate-method-error (email or login too small: '" + data.login + "')");
if (login.length() < 6) {
throw new InputException("login", "Authentiocate-method-error (email or login too small: '" + login + "')");
}
if(password == null || password.length() != 128) {
throw new InputException("password", "null password, or wrong hash size");
}
// email or login?
String query = "login";
if (data.login.contains("@")) {
if (login.contains("@")) {
query = "email";
}
UserAuth user = SqlWrapper.getWhere(UserAuth.class,
List.of(
new WhereCondition(query, "=", data.login)
new WhereCondition(query, "=", login)
),
false );
false );
if (user == null) {
throw new FailException(Response.Status.PRECONDITION_FAILED , "FAIL Authentiocate-wrong email/login '" + data.login + "')");
throw new FailException(Response.Status.PRECONDITION_FAILED , "FAIL Authentiocate-wrong email/login '" + login + "')");
}
// Check the password:
String passwodCheck = getSHA512("login='" + data.login + "';pass='" + user.password + "';date='" + data.time + "'");
if (!passwodCheck.contentEquals(data.password)) {
String passwodCheck = getSHA512("login='" + login + "';pass='" + user.password + "';date='" + time + "'");
if (!passwodCheck.contentEquals(password)) {
throw new FailException(Response.Status.PRECONDITION_FAILED , "Password error ...");
}
System.out.println(" ==> pass nearly all test : admin=" + user.admin + " blocked=" + user.blocked + " removed=" + user.removed);
if (user.blocked || user.removed) {
throw new FailException(Response.Status.UNAUTHORIZED, "FAIL Authentiocate");
}
return user;
}
@POST
@Path("/get_token")
@PermitAll
@Consumes(MediaType.APPLICATION_JSON)
public GetToken getToken(DataGetToken data) throws Exception {
UserAuth user = checkAuthUser(data.method, data.login, data.time, data.password);
int expirationTimeInMinutes = ConfigVariable.getAuthExpirationTime();
String ret = JWTWrapper.generateJWToken(user.id, user.login, ".", "sso", expirationTimeInMinutes);
String ret = JWTWrapper.generateJWToken(user.id, user.login, "KarAuth", "sso", expirationTimeInMinutes);
//System.out.println(" ==> generate token: " + ret);
return new GetToken(ret);
}

View File

@ -1,5 +1,9 @@
package org.kar.karso.model;
public class ChangePassword {
public String method;
public String login;
public String time;
public String password;
public String newPassword;
}

View File

@ -38,7 +38,7 @@ public class Settings extends GenericTable {
@SQLComment("Right for the specific element(ADMIN [rw] USER [rw] other [rw])")
@SQLNotNull
@SQLLimitSize(6)
@SQLDefault("rw----")
@SQLDefault("\"rw----\"")
public String right;
@SQLComment("Type Of the data")
@SQLNotNull

View File

@ -6,7 +6,7 @@
[style.border]="hasError? '2px dashed red' : ''"
[value]="value"
(input)="onChangeValue($event.target.value)" />
<button class="eye-button" (click)="onVisibility()" type="submit">
<button class="eye-button unselectable" tabindex="-1" (click)="onVisibility()" type="submit">
<i class="material-icons">{{passwordVisibility?"visibility":"visibility_off"}}</i>
</button>
</div>

View File

@ -32,6 +32,7 @@
img.avatar {
width: 150px;
border-radius: 50%;
user-select: none;
}
.container-global {

View File

@ -7,6 +7,7 @@
import { Component, OnInit } from '@angular/core';
import { Location } from '@angular/common';
import { createPasswordState } from 'common/utils';
import { AdminUserService } from 'app/service';
@Component({
selector: 'app-change-password',
@ -26,7 +27,8 @@ export class ChangePasswordScene {
public validateButtonDisabled: boolean = true;
constructor(
private locate: Location
private locate: Location,
private adminUserService: AdminUserService
) {}
/**
* update the state of the validation button. if all is OK, the button will became clickable
@ -85,7 +87,13 @@ export class ChangePasswordScene {
* Summit change password.
*/
onChangePassword(): void {
this.adminUserService.changePassword(this.passwordOld, this.password1)
.then(() => {
console.log(`Change password is OK`);
})
.catch((error: any) => {
console.error(`Fail to change PAssword: ${error}`);
});
}
/**
* Apply cancel on this page

View File

@ -37,7 +37,10 @@ export class AdminUserService {
// 0: Not hide password; 1 hide password;
private identificationVersion: number = 1;
constructor(private userService: UserService, private http: HttpWrapperService) {
constructor(
private userService: UserService,
private sessionService: SessionService,
private http: HttpWrapperService) {
console.log('Start AdminUserService');
}
/**
@ -215,4 +218,50 @@ export class AdminUserService {
retreivePassword(login: string): Promise<void> {
throw new Error('retreivePassword: Method not implemented.');
}
changePassword(oldPassword: string, newPassword: string): Promise<void> {
let time: string = new Date().toISOString();
let login: string = this.sessionService.getLogin();
let method = null;
let password = null;
if (this.identificationVersion === 1) {
method = 'v1';
password = sha512(`login='${login}';pass='${sha512(oldPassword)}';date='${time}'`);
} else {
return new Promise((resolve, reject) => {
reject(`Internal Fail (contact administrator).`);
});
}
let body = {
method,
time,
login,
password,
newPassword: sha512(newPassword),
}
let self = this;
return new Promise((resolve, reject) => {
self.http
.request({
server: 'karso',
endPoint: 'users/password',
requestType: HTTPRequestModel.POST,
accept: HTTPMimeType.JSON,
contentType: HTTPMimeType.JSON,
body,
})
.then((response: Response) => {
if (response.status >= 200 && response.status <= 299) {
console.log(`Update password done with sucess`);
resolve();
} else {
reject(`return ERROR to change password: ${response.status}`);
}
})
.catch((error: any) => {
reject(`return ERROR ${JSON.stringify(error, null, 2)}`);
});
});
}
}

View File

@ -252,6 +252,15 @@ label {
user-select: none;
}
.unselectable {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.fill-x {
width: 100%;
}