From f3ae1fcd1c402f1c2f3d63c8a63dfc5180ffee97 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Thu, 5 Jan 2023 00:13:10 +0100 Subject: [PATCH] [DEV] some back upgrade and add password change (no return GUI) --- back/pom.xml | 4 +- back/src/org/kar/karso/WebLauncher.java | 1 + .../kar/karso/api/ApplicationResource.java | 3 - .../kar/karso/api/SystemConfigResource.java | 58 +++++++------- back/src/org/kar/karso/api/UserResource.java | 78 ++++++++----------- .../org/kar/karso/model/ChangePassword.java | 4 + back/src/org/kar/karso/model/Settings.java | 2 +- .../password-entry/password-entry.html | 2 +- .../change-password/change-password.less | 1 + .../scene/change-password/change-password.ts | 12 ++- front/src/app/service/admin-user.ts | 51 +++++++++++- front/src/styles.less | 9 +++ 12 files changed, 140 insertions(+), 85 deletions(-) diff --git a/back/pom.xml b/back/pom.xml index 192190f..f3bd81a 100644 --- a/back/pom.xml +++ b/back/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.kar karso - 0.1.0 + 0.2.0 diff --git a/back/src/org/kar/karso/WebLauncher.java b/back/src/org/kar/karso/WebLauncher.java index 2cba9b2..9d57fa9 100755 --- a/back/src/org/kar/karso/WebLauncher.java +++ b/back/src/org/kar/karso/WebLauncher.java @@ -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); diff --git a/back/src/org/kar/karso/api/ApplicationResource.java b/back/src/org/kar/karso/api/ApplicationResource.java index 3582685..ef2d629 100755 --- a/back/src/org/kar/karso/api/ApplicationResource.java +++ b/back/src/org/kar/karso/api/ApplicationResource.java @@ -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); diff --git a/back/src/org/kar/karso/api/SystemConfigResource.java b/back/src/org/kar/karso/api/SystemConfigResource.java index 59f6fa9..5f8a5e0 100755 --- a/back/src/org/kar/karso/api/SystemConfigResource.java +++ b/back/src/org/kar/karso/api/SystemConfigResource.java @@ -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(); } diff --git a/back/src/org/kar/karso/api/UserResource.java b/back/src/org/kar/karso/api/UserResource.java index b8e61bf..293f3e3 100755 --- a/back/src/org/kar/karso/api/UserResource.java +++ b/back/src/org/kar/karso/api/UserResource.java @@ -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 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); } diff --git a/back/src/org/kar/karso/model/ChangePassword.java b/back/src/org/kar/karso/model/ChangePassword.java index 13231f1..f52eaa3 100644 --- a/back/src/org/kar/karso/model/ChangePassword.java +++ b/back/src/org/kar/karso/model/ChangePassword.java @@ -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; } diff --git a/back/src/org/kar/karso/model/Settings.java b/back/src/org/kar/karso/model/Settings.java index 1e5c61f..99614fa 100644 --- a/back/src/org/kar/karso/model/Settings.java +++ b/back/src/org/kar/karso/model/Settings.java @@ -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 diff --git a/front/src/app/component/password-entry/password-entry.html b/front/src/app/component/password-entry/password-entry.html index 7e22f38..e5e9ce9 100644 --- a/front/src/app/component/password-entry/password-entry.html +++ b/front/src/app/component/password-entry/password-entry.html @@ -6,7 +6,7 @@ [style.border]="hasError? '2px dashed red' : ''" [value]="value" (input)="onChangeValue($event.target.value)" /> - diff --git a/front/src/app/scene/change-password/change-password.less b/front/src/app/scene/change-password/change-password.less index 28ffa17..78deead 100644 --- a/front/src/app/scene/change-password/change-password.less +++ b/front/src/app/scene/change-password/change-password.less @@ -32,6 +32,7 @@ img.avatar { width: 150px; border-radius: 50%; + user-select: none; } .container-global { diff --git a/front/src/app/scene/change-password/change-password.ts b/front/src/app/scene/change-password/change-password.ts index aa51272..b64c23b 100644 --- a/front/src/app/scene/change-password/change-password.ts +++ b/front/src/app/scene/change-password/change-password.ts @@ -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 diff --git a/front/src/app/service/admin-user.ts b/front/src/app/service/admin-user.ts index 9a6c072..bc02d0e 100644 --- a/front/src/app/service/admin-user.ts +++ b/front/src/app/service/admin-user.ts @@ -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 { throw new Error('retreivePassword: Method not implemented.'); } + + changePassword(oldPassword: string, newPassword: string): Promise { + 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)}`); + }); + }); + } + } diff --git a/front/src/styles.less b/front/src/styles.less index a89c7d5..5da4641 100644 --- a/front/src/styles.less +++ b/front/src/styles.less @@ -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%; }