mirror of
				https://git.jami.net/savoirfairelinux/jami-jams.git
				synced 2025-10-30 07:57:19 +08:00 
			
		
		
		
	refactor: minor changes
- jams-react-client: fix request spam on devices tab - don't send hashed password in response when creating a user Change-Id: I3c576003d57ef84ff523ebbf14ac611793a8b750
This commit is contained in:
		| @ -1,5 +1,7 @@ | |||||||
| .git | .git | ||||||
| .gitignore | .gitignore | ||||||
|  | .gitmodules | ||||||
|  | .gitreview | ||||||
|  |  | ||||||
| Dockerfile | Dockerfile | ||||||
| .dockerignore | .dockerignore | ||||||
| @ -7,4 +9,13 @@ Dockerfile | |||||||
| **/node_modules | **/node_modules | ||||||
| **/target | **/target | ||||||
|  |  | ||||||
|  | .gradle | ||||||
|  | .idea | ||||||
|  | .vscode | ||||||
|  |  | ||||||
|  | README.md | ||||||
|  | derby.log | ||||||
|  |  | ||||||
|  | extras | ||||||
| jams | jams | ||||||
|  | jams-server/src/main/resources/webapp | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Dockerfile
									
									
									
									
									
								
							| @ -22,9 +22,9 @@ COPY jams-server/pom.xml jams-server/pom.xml | |||||||
| # RUN mvn dependency:resolve --fail-never | # RUN mvn dependency:resolve --fail-never | ||||||
| # RUN mvn dependency:go-offline --fail-never -am | # RUN mvn dependency:go-offline --fail-never -am | ||||||
| RUN mvn install -pl ad-connector,authentication-module,datastore,jami-dht,jami-nameserver,jams-ca,jams-common,jams-launcher,ldap-connector,jams-server -am -DskipTests | RUN mvn install -pl ad-connector,authentication-module,datastore,jami-dht,jami-nameserver,jams-ca,jams-common,jams-launcher,ldap-connector,jams-server -am -DskipTests | ||||||
| COPY . . |  | ||||||
|  |  | ||||||
| FROM build as dev | FROM build as dev | ||||||
|  | COPY . . | ||||||
| WORKDIR /app | WORKDIR /app | ||||||
| RUN mkdir -p /app/jams-server/src/main/resources/webapp \ | RUN mkdir -p /app/jams-server/src/main/resources/webapp \ | ||||||
|     && echo '<h1>Dev build, this is a placeholder index.html. Please connect to <a href="http://localhost:3000">localhost:3000</a> instead</h1>' \ |     && echo '<h1>Dev build, this is a placeholder index.html. Please connect to <a href="http://localhost:3000">localhost:3000</a> instead</h1>' \ | ||||||
| @ -38,18 +38,16 @@ CMD java -jar jams-server.jar 8080 \ | |||||||
|  |  | ||||||
| FROM build as prod | FROM build as prod | ||||||
| WORKDIR /app/jams-react-client | WORKDIR /app/jams-react-client | ||||||
|  | COPY jams-react-client . | ||||||
| RUN npm run build | RUN npm run build | ||||||
| RUN mkdir -p ../jams-server/src/main/resources/webapp \ |  | ||||||
|     && mv build/* ../jams-server/src/main/resources/webapp |  | ||||||
| WORKDIR /app | WORKDIR /app | ||||||
|  | COPY . . | ||||||
|  | RUN mkdir -p jams-server/src/main/resources/webapp \ | ||||||
|  |     && mv jams-react-client/build/* jams-server/src/main/resources/webapp | ||||||
| RUN mvn package | RUN mvn package | ||||||
|  |  | ||||||
| ENV JAMS_VERSION=3.5 | ENV JAMS_VERSION=3.5 | ||||||
| RUN python3 generate-versions.py net.jami.jams.ca.JamsCA $JAMS_VERSION libs/cryptoengine.jar | RUN python3 generate-versions.py $JAMS_VERSION | ||||||
| RUN python3 generate-versions.py net.jami.jams.authmodule.UserAuthenticationModule $JAMS_VERSION libs/authentication-module.jar |  | ||||||
| RUN python3 generate-versions.py net.jami.jams.server.Server $JAMS_VERSION jams-server.jar |  | ||||||
| RUN python3 generate-versions.py net.jami.jams.ad.connector.ADConnector $JAMS_VERSION libs/ad-connector.jar |  | ||||||
| RUN python3 generate-versions.py net.jami.jams.ldap.connector.LDAPConnector $JAMS_VERSION libs/ldap-connector.jar |  | ||||||
|  |  | ||||||
| RUN ./build-doc.sh | RUN ./build-doc.sh | ||||||
| WORKDIR /app/jams | WORKDIR /app/jams | ||||||
|  | |||||||
| @ -4,6 +4,9 @@ import sys | |||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  |  | ||||||
|  |  | ||||||
|  | here = Path(__file__).parent | ||||||
|  |  | ||||||
|  |  | ||||||
| def read_versions(versions_file: Path) -> dict: | def read_versions(versions_file: Path) -> dict: | ||||||
|     if not versions_file.exists(): |     if not versions_file.exists(): | ||||||
|         return {} |         return {} | ||||||
| @ -12,31 +15,57 @@ def read_versions(versions_file: Path) -> dict: | |||||||
|         return json.load(f) |         return json.load(f) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_md5_hash(filename: str) -> str: | ||||||
| def main() -> None: |  | ||||||
|     here = Path(__file__).parent |  | ||||||
|     versions_file = here / "versions.json" |  | ||||||
|  |  | ||||||
|     class_name = sys.argv[1] |  | ||||||
|     version = sys.argv[2] |  | ||||||
|     filename = sys.argv[3] |  | ||||||
|  |  | ||||||
|     versions = read_versions(versions_file) |  | ||||||
|  |  | ||||||
|     md5_hash = hashlib.md5() |     md5_hash = hashlib.md5() | ||||||
|  |  | ||||||
|     with open(here / "jams" / filename, "rb") as jar: |     with open(here / "jams" / filename, "rb") as jar: | ||||||
|         md5_hash.update(jar.read()) |         md5_hash.update(jar.read()) | ||||||
|  |  | ||||||
|  |     return md5_hash.hexdigest() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def generate_versions(class_name: str, version: str, filename: str) -> None: | ||||||
|  |     versions_file = here / "versions.json" | ||||||
|  |  | ||||||
|  |     versions = read_versions(versions_file) | ||||||
|  |  | ||||||
|     versions[class_name] = { |     versions[class_name] = { | ||||||
|         "version": version, |         "version": version, | ||||||
|         "filename": filename, |         "filename": filename, | ||||||
|         "md5": md5_hash.hexdigest(), |         "md5": get_md5_hash(filename), | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     with open(versions_file, "w") as f: |     with open(versions_file, "w") as f: | ||||||
|         json.dump(versions, f, indent=4) |         json.dump(versions, f, indent=4) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def main() -> None: | ||||||
|  |     if len(sys.argv) == 2: | ||||||
|  |         version = sys.argv[1] | ||||||
|  |  | ||||||
|  |         class_to_filename = { | ||||||
|  |             "net.jami.jams.ca.JamsCA": "libs/cryptoengine.jar", | ||||||
|  |             "net.jami.jams.authmodule.UserAuthenticationModule": "libs/authentication-module.jar", | ||||||
|  |             "net.jami.jams.server.Server": "jams-server.jar", | ||||||
|  |             "net.jami.jams.ad.connector.ADConnector": "libs/ad-connector.jar", | ||||||
|  |             "net.jami.jams.ldap.connector.LDAPConnector": "libs/ldap-connector.jar", | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         for class_name, filename in class_to_filename.items(): | ||||||
|  |             generate_versions(class_name, version, filename) | ||||||
|  |  | ||||||
|  |         return | ||||||
|  |  | ||||||
|  |     if len(sys.argv) != 4: | ||||||
|  |         print(f"Usage: {sys.argv[0]} (<version> | <class_name> <version> <filename>)") | ||||||
|  |         sys.exit(1) | ||||||
|  |  | ||||||
|  |     class_name = sys.argv[1] | ||||||
|  |     version = sys.argv[2] | ||||||
|  |     filename = sys.argv[3] | ||||||
|  |  | ||||||
|  |     generate_versions(class_name, version, filename) | ||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     main() |     main() | ||||||
|  | |||||||
| @ -44,6 +44,8 @@ import java.security.KeyPair; | |||||||
| import java.security.KeyPairGenerator; | import java.security.KeyPairGenerator; | ||||||
| import java.security.MessageDigest; | import java.security.MessageDigest; | ||||||
| import java.security.SecureRandom; | import java.security.SecureRandom; | ||||||
|  | import java.security.cert.CertificateEncodingException; | ||||||
|  | import java.security.cert.X509Certificate; | ||||||
| import java.util.Date; | import java.util.Date; | ||||||
|  |  | ||||||
| @Slf4j | @Slf4j | ||||||
| @ -51,7 +53,6 @@ public class UserBuilder { | |||||||
|  |  | ||||||
|     public static User generateUser(User user) { |     public static User generateUser(User user) { | ||||||
|         try { |         try { | ||||||
|             long now = System.currentTimeMillis(); |  | ||||||
|             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); |             KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); | ||||||
|             keyPairGenerator.initialize(4096); |             keyPairGenerator.initialize(4096); | ||||||
|             KeyPair keyPair = keyPairGenerator.generateKeyPair(); |             KeyPair keyPair = keyPairGenerator.generateKeyPair(); | ||||||
| @ -60,23 +61,14 @@ public class UserBuilder { | |||||||
|                     MessageDigest.getInstance(MessageDigestAlgorithms.SHA_1) |                     MessageDigest.getInstance(MessageDigestAlgorithms.SHA_1) | ||||||
|                             .digest(keyPair.getPublic().getEncoded()); |                             .digest(keyPair.getPublic().getEncoded()); | ||||||
|             user.getX509Fields().setUid(Hex.encodeHexString(digest)); |             user.getX509Fields().setUid(Hex.encodeHexString(digest)); | ||||||
|  |  | ||||||
|             X509v3CertificateBuilder builder = |  | ||||||
|                     new X509v3CertificateBuilder( |  | ||||||
|                             new JcaX509CertificateHolder(JamsCA.CA.getCertificate()).getSubject(), |  | ||||||
|                             new BigInteger(128, new SecureRandom()), |  | ||||||
|                             new Date(now - SHIFT), |  | ||||||
|                             new Date(now + JamsCA.userLifetime), |  | ||||||
|                             new X500Name(user.getX509Fields().getDN()), |  | ||||||
|                             SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded())); |  | ||||||
|  |  | ||||||
|             user.setPrivateKey(keyPair.getPrivate()); |             user.setPrivateKey(keyPair.getPrivate()); | ||||||
|             user.setCertificate( |  | ||||||
|                     CertificateSigner.signCertificate( |             String dn = user.getX509Fields().getDN(); | ||||||
|                             JamsCA.CA.getPrivateKey(), builder, ExtensionLibrary.userExtensions)); |             SubjectPublicKeyInfo publicKeyInfo = | ||||||
|             log.info( |                     SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()); | ||||||
|                     "New user certificate:  Not valid after: " |             X509Certificate certificate = | ||||||
|                             + user.getCertificate().getNotAfter()); |                     generateSignedCertificate(dn, JamsCA.userLifetime, publicKeyInfo); | ||||||
|  |             user.setCertificate(certificate); | ||||||
|             return user; |             return user; | ||||||
|         } catch (Exception e) { |         } catch (Exception e) { | ||||||
|             log.error("Could not generate a user certificate: " + e); |             log.error("Could not generate a user certificate: " + e); | ||||||
| @ -89,28 +81,18 @@ public class UserBuilder { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public static User refreshUser(User user, long userLifeTime) { |     public static User refreshUser(User user, long userLifeTime) { | ||||||
|         long now = System.currentTimeMillis(); |  | ||||||
|         X509Fields x509 = new X509Fields(); |         X509Fields x509 = new X509Fields(); | ||||||
|         x509.setCommonName(user.getUsername()); |         x509.setCommonName(user.getUsername()); | ||||||
|         x509.setUid(user.getJamiId()); |         x509.setUid(user.getJamiId()); | ||||||
|         user.setX509Fields(x509); |         user.setX509Fields(x509); | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             X509v3CertificateBuilder builder = |             String dn = user.getX509Fields().getDN(); | ||||||
|                     new X509v3CertificateBuilder( |             SubjectPublicKeyInfo publicKeyInfo = | ||||||
|                             new JcaX509CertificateHolder(JamsCA.CA.getCertificate()).getSubject(), |                     new JcaX509CertificateHolder(user.getCertificate()).getSubjectPublicKeyInfo(); | ||||||
|                             new BigInteger(128, new SecureRandom()), |             X509Certificate certificate = | ||||||
|                             new Date(now - SHIFT), |                     generateSignedCertificate(dn, userLifeTime, publicKeyInfo); | ||||||
|                             new Date(now + userLifeTime), |             user.setCertificate(certificate); | ||||||
|                             new X500Name(user.getX509Fields().getDN()), |  | ||||||
|                             new JcaX509CertificateHolder(user.getCertificate()) |  | ||||||
|                                     .getSubjectPublicKeyInfo()); |  | ||||||
|             user.setCertificate( |  | ||||||
|                     CertificateSigner.signCertificate( |  | ||||||
|                             JamsCA.CA.getPrivateKey(), builder, ExtensionLibrary.userExtensions)); |  | ||||||
|             log.info( |  | ||||||
|                     "Refreshed user certificate:  Not valid after: " |  | ||||||
|                             + user.getCertificate().getNotAfter()); |  | ||||||
|  |  | ||||||
|             return user; |             return user; | ||||||
|         } catch (Exception e) { |         } catch (Exception e) { | ||||||
| @ -118,4 +100,24 @@ public class UserBuilder { | |||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private static X509Certificate generateSignedCertificate( | ||||||
|  |             String dn, long userLifeTime, SubjectPublicKeyInfo publicKeyInfo) | ||||||
|  |             throws CertificateEncodingException { | ||||||
|  |         long now = System.currentTimeMillis(); | ||||||
|  |         X509v3CertificateBuilder builder = | ||||||
|  |                 new X509v3CertificateBuilder( | ||||||
|  |                         new JcaX509CertificateHolder(JamsCA.CA.getCertificate()).getSubject(), | ||||||
|  |                         new BigInteger(128, new SecureRandom()), | ||||||
|  |                         new Date(now - SHIFT), | ||||||
|  |                         new Date(now + userLifeTime), | ||||||
|  |                         new X500Name(dn), | ||||||
|  |                         publicKeyInfo); | ||||||
|  |  | ||||||
|  |         X509Certificate certificate = | ||||||
|  |                 CertificateSigner.signCertificate( | ||||||
|  |                         JamsCA.CA.getPrivateKey(), builder, ExtensionLibrary.userExtensions); | ||||||
|  |         log.info("User certificate:  Not valid after: {}", certificate.getNotAfter()); | ||||||
|  |         return certificate; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,39 +0,0 @@ | |||||||
| /* |  | ||||||
|  * Copyright (C) 2020 by Savoir-faire Linux |  | ||||||
|  * Authors: William Enright <william.enright@savoirfairelinux.com> |  | ||||||
|  *          Ndeye Anna Ndiaye <anna.ndiaye@savoirfairelinux.com> |  | ||||||
|  *          Johnny Flores <johnny.flores@savoirfairelinux.com> |  | ||||||
|  *          Mohammed Raza <mohammed.raza@savoirfairelinux.com> |  | ||||||
|  *          Felix Sidokhine <felix.sidokhine@savoirfairelinux.com> |  | ||||||
|  * |  | ||||||
|  * |  | ||||||
|  * This program is free software; you can redistribute it and/or modify |  | ||||||
|  * it under the terms of the GNU General Public License as published by |  | ||||||
|  * the Free Software Foundation; either version 3 of the License, or |  | ||||||
|  * (at your option) any later version. |  | ||||||
|  * |  | ||||||
|  * This program is distributed in the hope that it will be useful, |  | ||||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
|  * GNU General Public License for more details. |  | ||||||
|  * |  | ||||||
|  * You should have received a copy of the GNU General Public License |  | ||||||
|  * along with this program.  If not, see <https://www.gnu.org/licenses/>. |  | ||||||
|  */ |  | ||||||
| package net.jami.jams.common.objects.requests; |  | ||||||
|  |  | ||||||
| import lombok.Getter; |  | ||||||
| import lombok.Setter; |  | ||||||
|  |  | ||||||
| @Getter |  | ||||||
| @Setter |  | ||||||
| public class DeviceRevocationRequest { |  | ||||||
|  |  | ||||||
|     private String owner; |  | ||||||
|     private String deviceId; |  | ||||||
|  |  | ||||||
|     public DeviceRevocationRequest(String username, String deviceId) { |  | ||||||
|         this.owner = owner; |  | ||||||
|         this.deviceId = deviceId; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -25,7 +25,6 @@ public class ContactAdapter implements JsonSerializer<Contact>, JsonDeserializer | |||||||
|         contact.setUri(input.get("uri").getAsString()); |         contact.setUri(input.get("uri").getAsString()); | ||||||
|         contact.setConversationId(input.get("conversationId").getAsString()); |         contact.setConversationId(input.get("conversationId").getAsString()); | ||||||
|  |  | ||||||
|  |  | ||||||
|         long timeAdded = 0L; |         long timeAdded = 0L; | ||||||
|         if (input.has("added")) { |         if (input.has("added")) { | ||||||
|             timeAdded = input.get("added").getAsLong(); |             timeAdded = input.get("added").getAsLong(); | ||||||
|  | |||||||
| @ -66,6 +66,8 @@ public class X509Utils { | |||||||
|     private static final String PPK_TAIL = "\n-----END PUBLIC KEY-----"; |     private static final String PPK_TAIL = "\n-----END PUBLIC KEY-----"; | ||||||
|  |  | ||||||
|     public static PrivateKey getKeyFromPEMString(String keyString) { |     public static PrivateKey getKeyFromPEMString(String keyString) { | ||||||
|  |         if (keyString.isEmpty()) return null; | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             PEMParser parser = new PEMParser(new StringReader(keyString)); |             PEMParser parser = new PEMParser(new StringReader(keyString)); | ||||||
|             Object parsedObject = parser.readObject(); |             Object parsedObject = parser.readObject(); | ||||||
|  | |||||||
| @ -40,7 +40,7 @@ import i18next from "i18next"; | |||||||
|  |  | ||||||
| const useStyles = makeStyles(styles); | const useStyles = makeStyles(styles); | ||||||
|  |  | ||||||
| export default function Devices(props) { | export default function Devices({ username }) { | ||||||
|   const classes = useStyles(); |   const classes = useStyles(); | ||||||
|   const history = useHistory(); |   const history = useHistory(); | ||||||
|  |  | ||||||
| @ -49,9 +49,7 @@ export default function Devices(props) { | |||||||
|   const [displayName, setDisplayName] = useState(""); |   const [displayName, setDisplayName] = useState(""); | ||||||
|   const [openEdit, setOpenEdit] = useState(false); |   const [openEdit, setOpenEdit] = useState(false); | ||||||
|   const [openRevoke, setOpenRevoke] = useState(false); |   const [openRevoke, setOpenRevoke] = useState(false); | ||||||
|   const userData = { |   const userData = { username }; | ||||||
|     username: props.username, |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     auth.checkDirectoryType(() => { |     auth.checkDirectoryType(() => { | ||||||
| @ -94,7 +92,7 @@ export default function Devices(props) { | |||||||
|           }); |           }); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   }, [history, selectedDevice, userData]); |   }, []); | ||||||
|  |  | ||||||
|   function getDeviceStatus(device) { |   function getDeviceStatus(device) { | ||||||
|     if (!device.revoked) { |     if (!device.revoked) { | ||||||
| @ -134,7 +132,7 @@ export default function Devices(props) { | |||||||
|   const handleUpdate = () => { |   const handleUpdate = () => { | ||||||
|     if (auth.hasAdminScope()) { |     if (auth.hasAdminScope()) { | ||||||
|       const data = { |       const data = { | ||||||
|         username: props.username, |         username, | ||||||
|         deviceId: selectedDevice.deviceId, |         deviceId: selectedDevice.deviceId, | ||||||
|         deviceName: displayName, |         deviceName: displayName, | ||||||
|       }; |       }; | ||||||
| @ -188,7 +186,7 @@ export default function Devices(props) { | |||||||
|   const handleDeviceRevoke = () => { |   const handleDeviceRevoke = () => { | ||||||
|     if (auth.hasAdminScope()) { |     if (auth.hasAdminScope()) { | ||||||
|       const data = { |       const data = { | ||||||
|         username: props.username, |         username, | ||||||
|         deviceId: selectedDevice.deviceId, |         deviceId: selectedDevice.deviceId, | ||||||
|       }; |       }; | ||||||
|       axios( |       axios( | ||||||
|  | |||||||
| @ -1,9 +1,7 @@ | |||||||
| import React from "react"; | import React, { FC } from "react"; | ||||||
| // nodejs library to set properties for components |  | ||||||
| import PropTypes from "prop-types"; |  | ||||||
| // @mui/material components |  | ||||||
| import { makeStyles } from "@mui/styles"; | import { makeStyles } from "@mui/styles"; | ||||||
| import Grid from "@mui/material/Grid"; | import { Grid, GridTypeMap } from "@mui/material"; | ||||||
|  | import { OverridableComponent } from "@mui/material/OverridableComponent"; | ||||||
|  |  | ||||||
| const styles = { | const styles = { | ||||||
|   grid: { |   grid: { | ||||||
| @ -13,16 +11,17 @@ const styles = { | |||||||
|  |  | ||||||
| const useStyles = makeStyles(styles); | const useStyles = makeStyles(styles); | ||||||
|  |  | ||||||
| export default function GridItem(props) { | interface GridItemProps extends OverridableComponent<GridTypeMap> { | ||||||
|  |   children: React.ReactNode; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const GridItem: FC<GridItemProps> = ({ children, ...rest }) => { | ||||||
|   const classes = useStyles(); |   const classes = useStyles(); | ||||||
|   const { children, ...rest } = props; |  | ||||||
|   return ( |   return ( | ||||||
|     <Grid item {...rest} className={classes.grid}> |     <Grid item {...rest} className={classes.grid}> | ||||||
|       {children} |       {children} | ||||||
|     </Grid> |     </Grid> | ||||||
|   ); |   ); | ||||||
| } |  | ||||||
|  |  | ||||||
| GridItem.propTypes = { |  | ||||||
|   children: PropTypes.node, |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export default GridItem; | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ const uri = ""; | |||||||
| const current_uri = window.location.href; | const current_uri = window.location.href; | ||||||
| const backend_address = new URL( | const backend_address = new URL( | ||||||
|   process.env.NODE_ENV === "development" |   process.env.NODE_ENV === "development" | ||||||
|     ? "http://localhost:8080" |     ? window.location.origin.replace(/\d+$/, "") + "8080" | ||||||
|     : window.location.href |     : window.location.href | ||||||
| ); | ); | ||||||
| const url_path = backend_address.protocol + "//" + backend_address.hostname; | const url_path = backend_address.protocol + "//" + backend_address.hostname; | ||||||
|  | |||||||
| @ -39,7 +39,7 @@ export const PolicyDataContextProvider: FC<Props> = ({ | |||||||
|   children, |   children, | ||||||
| }) => { | }) => { | ||||||
|   const [policyData, setPolicyData] = useState(DEFAULT_POLICY_DATA); |   const [policyData, setPolicyData] = useState(DEFAULT_POLICY_DATA); | ||||||
|   const [snackbar, setSnackbar] = useState({ |   const [snackbar, setSnackbar] = useState<SnackbarProps>({ | ||||||
|     open: false, |     open: false, | ||||||
|     severity: "success", |     severity: "success", | ||||||
|     message: "", |     message: "", | ||||||
|  | |||||||
| @ -19,9 +19,7 @@ export const DEFAULT_UI_CUSTOMIZATION = { | |||||||
|   logoSize: 100, |   logoSize: 100, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export type UiCustomization = typeof DEFAULT_UI_CUSTOMIZATION; | const DEFAULT_POLICY_DATA_PERMISSIONS = { | ||||||
|  |  | ||||||
| export const DEFAULT_POLICY_DATA = { |  | ||||||
|   videoEnabled: true, |   videoEnabled: true, | ||||||
|   publicInCalls: false, |   publicInCalls: false, | ||||||
|   autoAnswer: false, |   autoAnswer: false, | ||||||
| @ -30,7 +28,9 @@ export const DEFAULT_POLICY_DATA = { | |||||||
|  |  | ||||||
|   rendezVous: false, |   rendezVous: false, | ||||||
|   blueprintModerators: [], |   blueprintModerators: [], | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | const DEFAULT_POLICY_DATA_CONFIGURATION = { | ||||||
|   upnpEnabled: true, |   upnpEnabled: true, | ||||||
|  |  | ||||||
|   selectedTurnOption: "defaultTurn", |   selectedTurnOption: "defaultTurn", | ||||||
| @ -41,8 +41,17 @@ export const DEFAULT_POLICY_DATA = { | |||||||
|   selectedDHTProxyOption: "defaultDHTProxy", |   selectedDHTProxyOption: "defaultDHTProxy", | ||||||
|   proxyServer: "dhtproxy.jami.net", |   proxyServer: "dhtproxy.jami.net", | ||||||
|   dhtProxyListUrl: "", |   dhtProxyListUrl: "", | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | export const DEFAULT_POLICY_DATA = { | ||||||
|  |   ...DEFAULT_POLICY_DATA_PERMISSIONS, | ||||||
|  |   ...DEFAULT_POLICY_DATA_CONFIGURATION, | ||||||
|   uiCustomization: DEFAULT_UI_CUSTOMIZATION, |   uiCustomization: DEFAULT_UI_CUSTOMIZATION, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export type PolicyData = typeof DEFAULT_POLICY_DATA; | export type UiCustomization = typeof DEFAULT_UI_CUSTOMIZATION; | ||||||
|  | export type PolicyDataPermissions = typeof DEFAULT_POLICY_DATA_PERMISSIONS; | ||||||
|  | export type PolicyDataNetwork = typeof DEFAULT_POLICY_DATA_CONFIGURATION; | ||||||
|  | export interface PolicyData extends PolicyDataPermissions, PolicyDataNetwork { | ||||||
|  |   uiCustomization: UiCustomization; | ||||||
|  | } | ||||||
|  | |||||||
| @ -186,8 +186,8 @@ export const _updatePolicyData = ( | |||||||
|   policyData: PolicyData, |   policyData: PolicyData, | ||||||
|   setPolicyData: Dispatch<SetStateAction<PolicyData>>, |   setPolicyData: Dispatch<SetStateAction<PolicyData>>, | ||||||
|   field: string, |   field: string, | ||||||
|   value: string, |   value: any, | ||||||
|   setSnackbar: (snackbar: any) => void |   setSnackbar: (snackbar: SnackbarProps) => void | ||||||
| ) => { | ) => { | ||||||
|   setPolicyData((state) => ({ ...state, [field]: value })); |   setPolicyData((state) => ({ ...state, [field]: value })); | ||||||
|  |  | ||||||
|  | |||||||
| @ -413,7 +413,6 @@ export default function Users(props) { | |||||||
|               xs={12} |               xs={12} | ||||||
|               sm={12} |               sm={12} | ||||||
|               md={2} |               md={2} | ||||||
|               wrap="nowrap" |  | ||||||
|               key={contact.uri} |               key={contact.uri} | ||||||
|               style={{ display: contact.display }} |               style={{ display: contact.display }} | ||||||
|             > |             > | ||||||
|  | |||||||
| @ -102,9 +102,8 @@ public class RegisterDeviceFlow { | |||||||
|                     }); |                     }); | ||||||
|             return response; |             return response; | ||||||
|         } catch (Exception e) { |         } catch (Exception e) { | ||||||
|             log.error( |             log.error("An exception has occurred while trying to enroll a device"); | ||||||
|                     "An exception has occurred while trying to enroll a device with error {}", |             e.printStackTrace(); | ||||||
|                     e.getMessage()); |  | ||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -38,15 +38,9 @@ import net.jami.jams.common.objects.contacts.Contact; | |||||||
| import net.jami.jams.common.objects.user.AccessLevel; | import net.jami.jams.common.objects.user.AccessLevel; | ||||||
| import net.jami.jams.common.serialization.adapters.GsonFactory; | import net.jami.jams.common.serialization.adapters.GsonFactory; | ||||||
| import net.jami.jams.common.serialization.tomcat.TomcatCustomErrorHandler; | import net.jami.jams.common.serialization.tomcat.TomcatCustomErrorHandler; | ||||||
| import net.jami.jams.common.utils.ContactMerger; |  | ||||||
|  |  | ||||||
| import org.json.JSONObject; |  | ||||||
|  |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.Arrays; |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Scanner; |  | ||||||
|  |  | ||||||
| @WebServlet("/api/admin/contacts") | @WebServlet("/api/admin/contacts") | ||||||
| public class ContactServlet extends HttpServlet { | public class ContactServlet extends HttpServlet { | ||||||
| @ -68,8 +62,8 @@ public class ContactServlet extends HttpServlet { | |||||||
|     @JsonContent |     @JsonContent | ||||||
|     protected void doGet(HttpServletRequest req, HttpServletResponse resp) |     protected void doGet(HttpServletRequest req, HttpServletResponse resp) | ||||||
|             throws ServletException, IOException { |             throws ServletException, IOException { | ||||||
|         List<Contact> contactList = |         String username = req.getParameter("username"); | ||||||
|                 dataStore.getContactDao().getByOwner(req.getParameter("username")); |         List<Contact> contactList = dataStore.getContactDao().getByOwner(username); | ||||||
|         resp.getOutputStream().write(gson.toJson(contactList).getBytes()); |         resp.getOutputStream().write(gson.toJson(contactList).getBytes()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -90,28 +84,9 @@ public class ContactServlet extends HttpServlet { | |||||||
|     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) |     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) | ||||||
|     protected void doPut(HttpServletRequest req, HttpServletResponse resp) |     protected void doPut(HttpServletRequest req, HttpServletResponse resp) | ||||||
|             throws ServletException, IOException { |             throws ServletException, IOException { | ||||||
|         Scanner s = new Scanner(req.getInputStream()).useDelimiter("\\A"); |         String username = req.getParameter("username"); | ||||||
|         String res = s.hasNext() ? s.next() : ""; |         net.jami.jams.server.servlets.api.auth.contacts.ContactServlet.addContact( | ||||||
|         final JSONObject obj = new JSONObject(res); |                 req, resp, username); | ||||||
|  |  | ||||||
|         Contact contact = new Contact(); |  | ||||||
|         // TODO: Replace with mergetool. |  | ||||||
|         contact.setDisplayName(obj.get("displayName").toString()); |  | ||||||
|         contact.setTimestamp(System.currentTimeMillis() / 1000); |  | ||||||
|         contact.setStatus('A'); |  | ||||||
|         contact.setOwner(req.getParameter("username")); |  | ||||||
|         contact.setUri(obj.get("uri").toString()); |  | ||||||
|  |  | ||||||
|         List<Contact> localList = |  | ||||||
|                 dataStore.getContactDao().getByOwner(req.getParameter("username")); |  | ||||||
|         List<Contact> remoteList = new ArrayList<>(); |  | ||||||
|         remoteList.add(contact); |  | ||||||
|         List<Contact> result = ContactMerger.mergeContacts(localList, remoteList); |  | ||||||
|  |  | ||||||
|         if (dataStore.getContactDao().storeContactList(result)) resp.setStatus(200); |  | ||||||
|         else |  | ||||||
|             TomcatCustomErrorHandler.sendCustomError( |  | ||||||
|                     resp, 500, "could not store a contact due to server-side error"); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @ -155,15 +130,8 @@ public class ContactServlet extends HttpServlet { | |||||||
|     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) |     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) | ||||||
|     protected void doPost(HttpServletRequest req, HttpServletResponse resp) |     protected void doPost(HttpServletRequest req, HttpServletResponse resp) | ||||||
|             throws ServletException, IOException { |             throws ServletException, IOException { | ||||||
|         List<Contact> localList = |         String username = req.getParameter("username"); | ||||||
|                 dataStore.getContactDao().getByOwner(req.getParameter("username")); |         net.jami.jams.server.servlets.api.auth.contacts.ContactServlet.addContacts( | ||||||
|         List<Contact> remoteList = Arrays.asList(gson.fromJson(req.getReader(), Contact[].class)); |                 req, resp, username); | ||||||
|  |  | ||||||
|         remoteList.forEach(contact -> contact.setOwner(req.getParameter("username"))); |  | ||||||
|         List<Contact> result = ContactMerger.mergeContacts(localList, remoteList); |  | ||||||
|  |  | ||||||
|         if (!dataStore.getContactDao().storeContactList(result)) |  | ||||||
|             TomcatCustomErrorHandler.sendCustomError(resp, 500, "Could not store contacts!"); |  | ||||||
|         else resp.getOutputStream().write(gson.toJson(result).getBytes()); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,6 +23,7 @@ | |||||||
| package net.jami.jams.server.servlets.api.admin.update; | package net.jami.jams.server.servlets.api.admin.update; | ||||||
|  |  | ||||||
| import com.google.gson.Gson; | import com.google.gson.Gson; | ||||||
|  | import com.google.gson.JsonObject; | ||||||
|  |  | ||||||
| import jakarta.servlet.ServletException; | import jakarta.servlet.ServletException; | ||||||
| import jakarta.servlet.annotation.WebServlet; | import jakarta.servlet.annotation.WebServlet; | ||||||
| @ -38,8 +39,6 @@ import net.jami.jams.common.serialization.adapters.GsonFactory; | |||||||
| import net.jami.jams.server.Server; | import net.jami.jams.server.Server; | ||||||
| import net.jami.jams.server.licensing.LicenseService; | import net.jami.jams.server.licensing.LicenseService; | ||||||
|  |  | ||||||
| import org.json.JSONObject; |  | ||||||
|  |  | ||||||
| import java.io.FileWriter; | import java.io.FileWriter; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  |  | ||||||
| @ -68,22 +67,18 @@ public class SubscriptionServlet extends HttpServlet { | |||||||
|     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) |     @ScopedServletMethod(securityGroups = {AccessLevel.ADMIN}) | ||||||
|     @JsonContent |     @JsonContent | ||||||
|     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { |     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { | ||||||
|         String license = new String(req.getInputStream().readAllBytes()); |         JsonObject jsonObject = gson.fromJson(req.getReader(), JsonObject.class); | ||||||
|         final JSONObject obj = new JSONObject(license); |         String license = jsonObject.get("base64License").getAsString(); | ||||||
|         license = obj.getString("base64License"); |  | ||||||
|  |  | ||||||
|         if (license != null || !license.isBlank()) { |         // create .dat file to be used later | ||||||
|             // create .dat file to be used later |         FileWriter fw = new FileWriter("license.dat"); | ||||||
|             FileWriter fw = new FileWriter("license.dat"); |         fw.write(license); | ||||||
|             fw.write(license); |         fw.close(); | ||||||
|             fw.close(); |  | ||||||
|             LicenseService licenseService = new LicenseService(); |         LicenseService licenseService = new LicenseService(); | ||||||
|             licenseService.loadLicense(); |         licenseService.loadLicense(); | ||||||
|             if (Server.activated.get()) { |         if (Server.activated.get()) { | ||||||
|                 resp.setStatus(200); |             resp.setStatus(200); | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|         resp.setStatus(500); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -37,7 +37,6 @@ import lombok.extern.slf4j.Slf4j; | |||||||
|  |  | ||||||
| import net.jami.jams.common.authentication.AuthenticationSourceType; | import net.jami.jams.common.authentication.AuthenticationSourceType; | ||||||
| import net.jami.jams.common.authmodule.AuthModuleKey; | import net.jami.jams.common.authmodule.AuthModuleKey; | ||||||
| import net.jami.jams.common.objects.user.User; |  | ||||||
| import net.jami.jams.common.objects.user.UserProfile; | import net.jami.jams.common.objects.user.UserProfile; | ||||||
| import net.jami.jams.common.serialization.adapters.GsonFactory; | import net.jami.jams.common.serialization.adapters.GsonFactory; | ||||||
|  |  | ||||||
| @ -203,55 +202,49 @@ public class DirectoryEntryServlet extends HttpServlet { | |||||||
|     protected void doGet(HttpServletRequest req, HttpServletResponse resp) |     protected void doGet(HttpServletRequest req, HttpServletResponse resp) | ||||||
|             throws ServletException, IOException { |             throws ServletException, IOException { | ||||||
|  |  | ||||||
|  |         String directory = req.getParameter("directory"); | ||||||
|  |         String directoryType = req.getParameter("directoryType"); | ||||||
|  |  | ||||||
|  |         String format = req.getParameter("format"); | ||||||
|  |         boolean isInVCardFormat = format != null && format.equals("vcard"); | ||||||
|  |  | ||||||
|         String jamiId = req.getParameter("jamiId"); |         String jamiId = req.getParameter("jamiId"); | ||||||
|         if (jamiId != null) { |  | ||||||
|             User user = dataStore.getUserDao().getByJamiId(jamiId).get(0); |         String username = | ||||||
|             List<UserProfile> userProfiles = new ArrayList<>(); |                 jamiId != null | ||||||
|             userAuthenticationModule |                         ? dataStore.getUserDao().getByJamiId(jamiId).get(0).getUsername() | ||||||
|                     .getAuthSources() |                         : req.getParameter("username"); | ||||||
|                     .forEach( |  | ||||||
|                             (k, v) -> { |         if (directory != null && directoryType != null) { | ||||||
|                                 userProfiles.addAll( |             AuthModuleKey authModuleKey = | ||||||
|                                         v.searchUserProfiles( |                     new AuthModuleKey( | ||||||
|                                                 user.getUsername(), |                             directory, AuthenticationSourceType.fromString(directoryType)); | ||||||
|                                                 "LOGON_NAME", |  | ||||||
|                                                 Optional.empty())); |             List<UserProfile> userProfiles = | ||||||
|                             }); |  | ||||||
|             if (req.getParameter("format") != null && req.getParameter("format").equals("vcard")) { |  | ||||||
|                 resp.getOutputStream().write(userProfiles.get(0).getAsVCard().getBytes()); |  | ||||||
|             } else resp.getOutputStream().write(gson.toJson(userProfiles.get(0)).getBytes()); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         if (req.getParameter("directory") != null && req.getParameter("directoryType") != null) { |  | ||||||
|             List<UserProfile> profiles = |  | ||||||
|                     userAuthenticationModule |                     userAuthenticationModule | ||||||
|                             .getAuthSources() |                             .getAuthSources() | ||||||
|                             .get( |                             .get(authModuleKey) | ||||||
|                                     new AuthModuleKey( |                             .searchUserProfiles(username, "LOGON_NAME", Optional.empty()); | ||||||
|                                             req.getParameter("directory"), |  | ||||||
|                                             AuthenticationSourceType.fromString( |             UserProfile userProfile = userProfiles.get(0); | ||||||
|                                                     req.getParameter("directoryType")))) |             String result = isInVCardFormat ? userProfile.getAsVCard() : gson.toJson(userProfile); | ||||||
|                             .searchUserProfiles( |             resp.getOutputStream().write(result.getBytes()); | ||||||
|                                     req.getParameter("username"), "LOGON_NAME", Optional.empty()); |  | ||||||
|             if (req.getParameter("format") != null && req.getParameter("format").equals("vcard")) { |  | ||||||
|                 resp.getOutputStream().write(profiles.get(0).getAsVCard().getBytes()); |  | ||||||
|             } else resp.getOutputStream().write(gson.toJson(profiles.get(0)).getBytes()); |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         List<UserProfile> userProfiles = new ArrayList<>(); |         List<UserProfile> userProfiles = new ArrayList<>(); | ||||||
|         userAuthenticationModule |         userAuthenticationModule | ||||||
|                 .getAuthSources() |                 .getAuthSources() | ||||||
|  |                 .values() | ||||||
|                 .forEach( |                 .forEach( | ||||||
|                         (k, v) -> { |                         v -> { | ||||||
|                             userProfiles.addAll( |                             userProfiles.addAll( | ||||||
|                                     v.searchUserProfiles( |                                     v.searchUserProfiles(username, "LOGON_NAME", Optional.empty())); | ||||||
|                                             req.getParameter("username"), |  | ||||||
|                                             "LOGON_NAME", |  | ||||||
|                                             Optional.empty())); |  | ||||||
|                         }); |                         }); | ||||||
|         if (req.getParameter("format") != null && req.getParameter("format").equals("vcard")) { |  | ||||||
|             resp.getOutputStream().write(userProfiles.get(0).getAsVCard().getBytes()); |         UserProfile userProfile = userProfiles.get(0); | ||||||
|         } else resp.getOutputStream().write(gson.toJson(userProfiles.get(0)).getBytes()); |         String result = isInVCardFormat ? userProfile.getAsVCard() : gson.toJson(userProfile); | ||||||
|  |         resp.getOutputStream().write(result.getBytes()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| package net.jami.jams.server.servlets.api.image; | package net.jami.jams.server.servlets.api.image; | ||||||
|  |  | ||||||
|  | import com.google.gson.Gson; | ||||||
|  |  | ||||||
| import jakarta.servlet.ServletException; | import jakarta.servlet.ServletException; | ||||||
| import jakarta.servlet.annotation.MultipartConfig; | import jakarta.servlet.annotation.MultipartConfig; | ||||||
| import jakarta.servlet.annotation.WebServlet; | import jakarta.servlet.annotation.WebServlet; | ||||||
| @ -9,6 +11,7 @@ import jakarta.servlet.http.HttpServletResponse; | |||||||
| import jakarta.servlet.http.Part; | import jakarta.servlet.http.Part; | ||||||
|  |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  |  | ||||||
| import net.jami.jams.common.serialization.adapters.GsonFactory; | import net.jami.jams.common.serialization.adapters.GsonFactory; | ||||||
|  |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| @ -20,8 +23,6 @@ import java.nio.file.Paths; | |||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
|  |  | ||||||
| import com.google.gson.Gson; |  | ||||||
|  |  | ||||||
| @MultipartConfig | @MultipartConfig | ||||||
| @Slf4j | @Slf4j | ||||||
| @WebServlet("/api/image/filehandler/*") | @WebServlet("/api/image/filehandler/*") | ||||||
| @ -87,7 +88,8 @@ public class FileHandlerServlet extends HttpServlet { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             Map<String, String> map = new HashMap<>(); |             Map<String, String> map = new HashMap<>(); | ||||||
|             String url = "/api/image/filehandler/" + blueprintName + "/" + imageType + "/" + fileName; |             String url = | ||||||
|  |                     "/api/image/filehandler/" + blueprintName + "/" + imageType + "/" + fileName; | ||||||
|             map.put("url", url); |             map.put("url", url); | ||||||
|  |  | ||||||
|             Gson gson = GsonFactory.createGson(); |             Gson gson = GsonFactory.createGson(); | ||||||
|  | |||||||
| @ -95,9 +95,7 @@ public class FilterUtils { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             String username = token.getJWTClaimsSet().getSubject(); |             String username = token.getJWTClaimsSet().getSubject(); | ||||||
|             log.info("Getting user from database"); |  | ||||||
|             User user = dataStore.getUserDao().getByUsername(username).orElseThrow(); |             User user = dataStore.getUserDao().getByUsername(username).orElseThrow(); | ||||||
|             log.info("User retrieved from database: {}", user); |  | ||||||
|  |  | ||||||
|             if (!user.getAccessLevelName().equals("ADMIN") |             if (!user.getAccessLevelName().equals("ADMIN") | ||||||
|                     && certificateAuthority.getLatestCRL().get() != null) { |                     && certificateAuthority.getLatestCRL().get() != null) { | ||||||
|  | |||||||
| @ -38,7 +38,11 @@ import org.ldaptive.SearchRequest; | |||||||
| import org.ldaptive.SearchResponse; | import org.ldaptive.SearchResponse; | ||||||
|  |  | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| import java.util.*; | import java.util.ArrayList; | ||||||
|  | import java.util.Collection; | ||||||
|  | import java.util.HashMap; | ||||||
|  | import java.util.List; | ||||||
|  | import java.util.Optional; | ||||||
| import java.util.stream.Collectors; | import java.util.stream.Collectors; | ||||||
|  |  | ||||||
| @Slf4j | @Slf4j | ||||||
| @ -58,45 +62,23 @@ public class UserProfileService { | |||||||
|                             queryString.getBytes(StandardCharsets.UTF_8), |                             queryString.getBytes(StandardCharsets.UTF_8), | ||||||
|                             StandardCharsets.ISO_8859_1); |                             StandardCharsets.ISO_8859_1); | ||||||
|             connection = connectionFactory.getConnection(); |             connection = connectionFactory.getConnection(); | ||||||
|             try { |             connection.open(); | ||||||
|                 connection.open(); |             SearchOperation search = new SearchOperation(connectionFactory); | ||||||
|                 SearchOperation search = new SearchOperation(connectionFactory); |             SearchResponse res = search.execute(buildRequest(queryString, field, exactMatch)); | ||||||
|                 SearchResponse res = search.execute(buildRequest(queryString, field, exactMatch)); |  | ||||||
|  |  | ||||||
|                 DataStore.NUM_PAGES = |             Collection<LdapEntry> entries = getEntriesPage(res, page); | ||||||
|                         (Integer) res.getEntries().size() / DataStore.RESULTS_PER_PAGE; |  | ||||||
|                 if (res.getEntries().size() % DataStore.RESULTS_PER_PAGE != 0) |  | ||||||
|                     DataStore.NUM_PAGES++; |  | ||||||
|  |  | ||||||
|                 if (page.isPresent() && !res.getEntries().isEmpty()) { |             if (entries.isEmpty()) return new ArrayList<>(); | ||||||
|                     if (res.getEntries().size() < DataStore.RESULTS_PER_PAGE) |  | ||||||
|                         res = res.subResult(0, res.getEntries().size()); |  | ||||||
|                     else if (page.get() * DataStore.RESULTS_PER_PAGE > res.getEntries().size()) |  | ||||||
|                         res = |  | ||||||
|                                 res.subResult( |  | ||||||
|                                         (page.get() - 1) * DataStore.RESULTS_PER_PAGE, |  | ||||||
|                                         res.getEntries().size()); |  | ||||||
|                     else |  | ||||||
|                         res = |  | ||||||
|                                 res.subResult( |  | ||||||
|                                         (page.get() - 1) * DataStore.RESULTS_PER_PAGE, |  | ||||||
|                                         (page.get() * DataStore.RESULTS_PER_PAGE)); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 if (res.getEntries().size() == 0) return new ArrayList<>(); |             List<UserProfile> profilesFromResponse = | ||||||
|                 List<UserProfile> profilesFromResponse = |                     entries.stream() | ||||||
|                         res.getEntries().stream() |                             .map(UserProfileService::profileFromResponse) | ||||||
|                                 .map(UserProfileService::profileFromResponse) |                             .collect(Collectors.toList()); | ||||||
|                                 .collect(Collectors.toList()); |             for (UserProfile p : profilesFromResponse) { | ||||||
|                 for (UserProfile p : profilesFromResponse) { |                 dataStore.getUserProfileDao().insertIfNotExists(p); | ||||||
|                     dataStore.getUserProfileDao().insertIfNotExists(p); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 return profilesFromResponse; |  | ||||||
|             } catch (Exception e) { |  | ||||||
|                 log.error("Could not search LDAP directory with error " + e); |  | ||||||
|                 return null; |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             return profilesFromResponse; | ||||||
|         } catch (Exception e) { |         } catch (Exception e) { | ||||||
|             log.info("Failed to search LDAP directory with error " + e); |             log.info("Failed to search LDAP directory with error " + e); | ||||||
|             return null; |             return null; | ||||||
| @ -105,6 +87,28 @@ public class UserProfileService { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private Collection<LdapEntry> getEntriesPage(SearchResponse res, Optional<Integer> page) { | ||||||
|  |         int size = res.getEntries().size(); | ||||||
|  |  | ||||||
|  |         DataStore.NUM_PAGES = (Integer) size / DataStore.RESULTS_PER_PAGE; | ||||||
|  |         if (size % DataStore.RESULTS_PER_PAGE != 0) DataStore.NUM_PAGES++; | ||||||
|  |  | ||||||
|  |         if (page.isEmpty() || size == 0) { | ||||||
|  |             return res.getEntries(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (size < DataStore.RESULTS_PER_PAGE) res = res.subResult(0, size); | ||||||
|  |         else if (page.get() * DataStore.RESULTS_PER_PAGE > size) | ||||||
|  |             res = res.subResult((page.get() - 1) * DataStore.RESULTS_PER_PAGE, size); | ||||||
|  |         else | ||||||
|  |             res = | ||||||
|  |                     res.subResult( | ||||||
|  |                             (page.get() - 1) * DataStore.RESULTS_PER_PAGE, | ||||||
|  |                             (page.get() * DataStore.RESULTS_PER_PAGE)); | ||||||
|  |  | ||||||
|  |         return res.getEntries(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public static SearchRequest buildRequest(String queryString, String field, boolean exactMatch) { |     public static SearchRequest buildRequest(String queryString, String field, boolean exactMatch) { | ||||||
|  |  | ||||||
|         if (!exactMatch) { |         if (!exactMatch) { | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Léo Banno-Cloutier
					Léo Banno-Cloutier