/** * ============================================================================= * * ORCID (R) Open Source * http://orcid.org * * Copyright (c) 2012-2014 ORCID, Inc. * Licensed under an MIT-Style License (MIT) * http://orcid.org/open-source-license * * This copyright and license information (including a link to the full license) * shall be included in its entirety in all copies or substantial portion of * the software. * * ============================================================================= */ package org.orcid.core.cli; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.util.Date; import java.util.UUID; import org.kohsuke.args4j.CmdLineException; import org.kohsuke.args4j.CmdLineParser; import org.kohsuke.args4j.Option; import org.orcid.core.manager.ClientDetailsManager; import org.orcid.core.manager.EncryptionManager; import org.orcid.persistence.jpa.entities.ClientDetailsEntity; import org.orcid.persistence.jpa.entities.ClientSecretEntity; import org.orcid.utils.DateUtils; import org.orcid.utils.NullUtils; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; /** * * @author Will Simpson * */ public class CreateNewClientSecrets { private Date now = new Date(); private String dateString = DateUtils.convertToXMLGregorianCalendar(now).toXMLFormat(); @Option(name = "-c", usage = "Client details id for which to create new secret") private String clientDetailsId; @Option(name = "-a", usage = "Create new client secret for all clients") private Boolean doAll; @Option(name = "-f", usage = "File from which to read client ids to create new secrets for (one per line)") private File clientIdsFile; @Option(name = "-o", usage = "File to write the results to (default is client_secrets_DATETIME)") private File outputFile = new File(System.getProperty("java.io.tmpdir"), "client_secrets_" + dateString); private BufferedWriter outputWriter; private EncryptionManager encryptionManager; private ClientDetailsManager clientDetailsManager; private TransactionTemplate transactionTemplate; public static void main(String[] args) { CreateNewClientSecrets createNewClientSecrets = new CreateNewClientSecrets(); CmdLineParser parser = new CmdLineParser(createNewClientSecrets); try { parser.parseArgument(args); createNewClientSecrets.validateArgs(parser); createNewClientSecrets.execute(); } catch (CmdLineException e) { System.err.println(e.getMessage()); parser.printUsage(System.err); } finally { System.exit(0); } } private void validateArgs(CmdLineParser parser) throws CmdLineException { if (NullUtils.allNull(clientDetailsId, doAll, clientIdsFile)) { throw new CmdLineException(parser, "At least one of -c | -a | -f must be specificed"); } } public void execute() { init(); openOutputFileAndCreateNewSecrets(); finish(); } private void openOutputFileAndCreateNewSecrets() { try (FileWriter fr = new FileWriter(outputFile); BufferedWriter br = new BufferedWriter(fr)) { makeOutputFileReadableToOwnerOnly(); outputWriter = br; createNewSecrets(); } catch (IOException e) { throw new RuntimeException("Problem opening output file " + outputFile.getAbsolutePath(), e); } } private void createNewSecrets() { if (Boolean.TRUE.equals(doAll)) { createForAll(); } else { if (clientDetailsId != null) { createForOne(clientDetailsId); } else if (clientIdsFile != null) { createFromFile(); } } } private void createForOne(final String clientDetailsId) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { ClientDetailsEntity clientDetails = clientDetailsManager.findByClientId(clientDetailsId); createNewClientSecret(clientDetails); } }); } private void createForAll() { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus status) { for (ClientDetailsEntity clientDetails : clientDetailsManager.getAll()) { createNewClientSecret(clientDetails); } } }); } private void createFromFile() { try (Reader fr = new FileReader(clientIdsFile); BufferedReader br = new BufferedReader(fr);) { String line = null; while ((line = br.readLine()) != null) { String clientDetailsId = line.trim(); createForOne(clientDetailsId); } } catch (FileNotFoundException e) { throw new RuntimeException("Client IDs file " + clientIdsFile.getAbsolutePath() + " not found", e); } catch (IOException e) { throw new RuntimeException("Error reading client IDs file " + clientIdsFile.getAbsolutePath() + " not found", e); } } private void createNewClientSecret(ClientDetailsEntity clientDetails) { String clientSecret = UUID.randomUUID().toString(); clientDetails.getClientSecrets().add(new ClientSecretEntity(encryptionManager.encryptForInternalUse(clientSecret), clientDetails)); clientDetails.setLastModified(now); clientDetailsManager.merge(clientDetails); String output = String.format("%s\t%s\t%s\n", clientDetails.getId(), clientDetails.getClientName(), clientSecret); output(output); } @SuppressWarnings("resource") private void init() { ApplicationContext context = new ClassPathXmlApplicationContext("orcid-core-context.xml"); encryptionManager = (EncryptionManager) context.getBean("encryptionManager"); clientDetailsManager = (ClientDetailsManager) context.getBean("clientDetailsManager"); transactionTemplate = (TransactionTemplate) context.getBean("transactionTemplate"); } private void makeOutputFileReadableToOwnerOnly() throws IOException { outputFile.createNewFile(); outputFile.setReadable(false, false); outputFile.setReadable(true, true); } private void output(String output) { System.out.print(output); try { outputWriter.append(output); } catch (IOException e) { throw new RuntimeException("Error writing to output file", e); } } private void finish() { System.out.println(">>>>>>>> Results output to " + outputFile.getAbsolutePath()); System.out.println(">>>>>>>> MAKE SURE YOU CLEAN UP THE OUTPUT FILE WHEN YOU HAVE FINISHED!!!!!"); } }