SSH-command : set-account
Added a new command, 'set-account', that can be used to edit
various settings of an account, such as active status,
emails, ssh keys and the full name.
The commandline pattern:
set-account [--full-name <FULLNAME>] [--active|--inactive]
            [--add-email <EMAIL>] [--delete-email <EMAIL> | ALL]
            [--add-ssh-key - | <KEY>]
            [--delete-ssh-key - | <KEY> | ALL] <USER>
Bug: issue 1095
Change-Id: Ice168daad59db3812b2db7e5f055931ebc073df7
			
			
This commit is contained in:
		 Deniz Turkoglu
					Deniz Turkoglu
				
			
				
					committed by
					
						 Deniz Türkoglu
						Deniz Türkoglu
					
				
			
			
				
	
			
			
			 Deniz Türkoglu
						Deniz Türkoglu
					
				
			
						parent
						
							90ff393d02
						
					
				
				
					commit
					2c4bbcffc3
				
			| @@ -0,0 +1,273 @@ | ||||
| // Copyright (C) 2012 The Android Open Source Project | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| package com.google.gerrit.sshd.commands; | ||||
|  | ||||
|  | ||||
| import com.google.gerrit.common.errors.InvalidSshKeyException; | ||||
| import com.google.gerrit.reviewdb.client.Account; | ||||
| import com.google.gerrit.reviewdb.client.Account.FieldName; | ||||
| import com.google.gerrit.reviewdb.client.AccountExternalId; | ||||
| import com.google.gerrit.reviewdb.client.AccountSshKey; | ||||
| import com.google.gerrit.reviewdb.server.ReviewDb; | ||||
| import com.google.gerrit.server.IdentifiedUser; | ||||
| import com.google.gerrit.server.account.AccountCache; | ||||
| import com.google.gerrit.server.account.AccountException; | ||||
| import com.google.gerrit.server.account.AccountManager; | ||||
| import com.google.gerrit.server.account.AuthRequest; | ||||
| import com.google.gerrit.server.account.Realm; | ||||
| import com.google.gerrit.server.ssh.SshKeyCache; | ||||
| import com.google.gerrit.sshd.BaseCommand; | ||||
| import com.google.gwtorm.server.OrmException; | ||||
| import com.google.gwtorm.server.ResultSet; | ||||
| import com.google.inject.Inject; | ||||
|  | ||||
| import org.apache.sshd.server.Environment; | ||||
| import org.kohsuke.args4j.Argument; | ||||
| import org.kohsuke.args4j.Option; | ||||
|  | ||||
| import java.io.BufferedReader; | ||||
| import java.io.IOException; | ||||
| import java.io.InputStreamReader; | ||||
| import java.io.UnsupportedEncodingException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
|  | ||||
| /** Set a user's account settings. **/ | ||||
| final class SetAccountCommand extends BaseCommand { | ||||
|  | ||||
|   @Argument(index = 0, required = true, metaVar = "USER", usage = "full name, email-address, ssh username or account id") | ||||
|   private Account.Id id; | ||||
|  | ||||
|   @Option(name = "--full-name", metaVar = "NAME", usage = "display name of the account") | ||||
|   private String fullName; | ||||
|  | ||||
|   @Option(name = "--active", usage = "set account's state to active") | ||||
|   private boolean active; | ||||
|  | ||||
|   @Option(name = "--inactive", usage = "set account's state to inactive") | ||||
|   private boolean inactive; | ||||
|  | ||||
|   @Option(name = "--add-email", multiValued = true, metaVar = "EMAIL", usage = "email addresses to add to the account") | ||||
|   private List<String> addEmails = new ArrayList<String>(); | ||||
|  | ||||
|   @Option(name = "--delete-email", multiValued = true, metaVar = "EMAIL", usage = "email addresses to delete from the account") | ||||
|   private List<String> deleteEmails = new ArrayList<String>(); | ||||
|  | ||||
|   @Option(name = "--add-ssh-key", multiValued = true, metaVar = "-|KEY", usage = "public keys to add to the account") | ||||
|   private List<String> addSshKeys = new ArrayList<String>(); | ||||
|  | ||||
|   @Option(name = "--delete-ssh-key", multiValued = true, metaVar = "-|KEY", usage = "public keys to delete from the account") | ||||
|   private List<String> deleteSshKeys = new ArrayList<String>(); | ||||
|  | ||||
|   @Inject | ||||
|   private IdentifiedUser currentUser; | ||||
|  | ||||
|   @Inject | ||||
|   private ReviewDb db; | ||||
|  | ||||
|   @Inject | ||||
|   private AccountManager manager; | ||||
|  | ||||
|   @Inject | ||||
|   private SshKeyCache sshKeyCache; | ||||
|  | ||||
|   @Inject | ||||
|   private AccountCache byIdCache; | ||||
|  | ||||
|   @Inject | ||||
|   private Realm realm; | ||||
|  | ||||
|   @Override | ||||
|   public void start(final Environment env) { | ||||
|     startThread(new CommandRunnable() { | ||||
|       @Override | ||||
|       public void run() throws Exception { | ||||
|         if (!currentUser.getCapabilities().canAdministrateServer()) { | ||||
|           String msg = | ||||
|               String.format( | ||||
|                   "fatal: %s does not have \"Administrator\" capability.", | ||||
|                   currentUser.getUserName()); | ||||
|           throw new UnloggedFailure(1, msg); | ||||
|         } | ||||
|         parseCommandLine(); | ||||
|         validate(); | ||||
|         setAccount(); | ||||
|       } | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   private void validate() throws UnloggedFailure { | ||||
|     if (active && inactive) { | ||||
|       throw new UnloggedFailure(1, | ||||
|           "--active and --inactive options are mutually exclusive."); | ||||
|     } | ||||
|     if (addSshKeys.contains("-") && deleteSshKeys.contains("-")) { | ||||
|       throw new UnloggedFailure(1, "Only one option may use the stdin"); | ||||
|     } | ||||
|     if (deleteSshKeys.contains("ALL")) { | ||||
|       deleteSshKeys = Collections.singletonList("ALL"); | ||||
|     } | ||||
|     if (deleteEmails.contains("ALL")) { | ||||
|       deleteEmails = Collections.singletonList("ALL"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private void setAccount() throws OrmException, IOException, UnloggedFailure { | ||||
|  | ||||
|     final Account account = db.accounts().get(id); | ||||
|     boolean accountUpdated = false; | ||||
|     boolean sshKeysUpdated = false; | ||||
|  | ||||
|     for (String email : addEmails) { | ||||
|       link(id, email); | ||||
|     } | ||||
|  | ||||
|     for (String email : deleteEmails) { | ||||
|       deleteMail(id, email); | ||||
|     } | ||||
|  | ||||
|     if (fullName != null) { | ||||
|       if (realm.allowsEdit(FieldName.FULL_NAME)) { | ||||
|         account.setFullName(fullName); | ||||
|       } else { | ||||
|         throw new UnloggedFailure(1, "The realm doesn't allow editing names"); | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if (active) { | ||||
|       accountUpdated = true; | ||||
|       account.setActive(true); | ||||
|     } else if (inactive) { | ||||
|       accountUpdated = true; | ||||
|       account.setActive(false); | ||||
|     } | ||||
|  | ||||
|     addSshKeys = readSshKey(addSshKeys); | ||||
|     if (!addSshKeys.isEmpty()) { | ||||
|       sshKeysUpdated = true; | ||||
|       addSshKeys(addSshKeys, account); | ||||
|     } | ||||
|  | ||||
|     deleteSshKeys = readSshKey(deleteSshKeys); | ||||
|     if (!deleteSshKeys.isEmpty()) { | ||||
|       sshKeysUpdated = true; | ||||
|       deleteSshKeys(deleteSshKeys, account); | ||||
|     } | ||||
|  | ||||
|     if (accountUpdated) { | ||||
|       db.accounts().update(Collections.singleton(account)); | ||||
|       byIdCache.evict(id); | ||||
|     } | ||||
|  | ||||
|     if (sshKeysUpdated) { | ||||
|       sshKeyCache.evict(account.getUserName()); | ||||
|     } | ||||
|  | ||||
|     db.close(); | ||||
|   } | ||||
|  | ||||
|   private void addSshKeys(final List<String> keys, final Account account) | ||||
|       throws OrmException, UnloggedFailure { | ||||
|     List<AccountSshKey> accountKeys = new ArrayList<AccountSshKey>(); | ||||
|     int seq = db.accountSshKeys().byAccount(account.getId()).toList().size(); | ||||
|     for (String key : keys) { | ||||
|       try { | ||||
|         seq++; | ||||
|         AccountSshKey accountSshKey = sshKeyCache.create( | ||||
|             new AccountSshKey.Id(account.getId(), seq), key.trim()); | ||||
|         accountKeys.add(accountSshKey); | ||||
|       } catch (InvalidSshKeyException e) { | ||||
|         throw new UnloggedFailure(1, "fatal: invalid ssh key"); | ||||
|       } | ||||
|     } | ||||
|     db.accountSshKeys().insert(accountKeys); | ||||
|   } | ||||
|  | ||||
|   private void deleteSshKeys(final List<String> keys, final Account account) | ||||
|       throws OrmException { | ||||
|     ResultSet<AccountSshKey> allKeys = db.accountSshKeys().byAccount(account.getId()); | ||||
|     if (keys.contains("ALL")) { | ||||
|       db.accountSshKeys().delete(allKeys); | ||||
|     } else { | ||||
|       List<AccountSshKey> accountKeys = new ArrayList<AccountSshKey>(); | ||||
|       for (String key : keys) { | ||||
|         for (AccountSshKey accountSshKey : allKeys) { | ||||
|           if (key.trim().equals(accountSshKey.getSshPublicKey()) | ||||
|               || accountSshKey.getComment().trim().equals(key)) { | ||||
|             accountKeys.add(accountSshKey); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       db.accountSshKeys().delete(accountKeys); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private void deleteMail(Account.Id id, final String mailAddress) | ||||
|       throws UnloggedFailure, OrmException { | ||||
|     if (mailAddress.equals("ALL")) { | ||||
|       ResultSet<AccountExternalId> ids = db.accountExternalIds().byAccount(id); | ||||
|       for (AccountExternalId extId : ids) { | ||||
|         if (extId.isScheme(AccountExternalId.SCHEME_MAILTO)) { | ||||
|           unlink(id, extId.getEmailAddress()); | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       AccountExternalId.Key key = new AccountExternalId.Key( | ||||
|           AccountExternalId.SCHEME_MAILTO, mailAddress); | ||||
|       AccountExternalId extId = db.accountExternalIds().get(key); | ||||
|       if (extId != null) { | ||||
|         unlink(id, mailAddress); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private void unlink(Account.Id id, final String mailAddress) | ||||
|       throws UnloggedFailure { | ||||
|     try { | ||||
|       manager.unlink(id, AuthRequest.forEmail(mailAddress)); | ||||
|     } catch (AccountException ex) { | ||||
|       throw die(ex.getMessage()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private void link(Account.Id id, final String mailAddress) | ||||
|       throws UnloggedFailure { | ||||
|     try { | ||||
|       manager.link(id, AuthRequest.forEmail(mailAddress)); | ||||
|     } catch (AccountException ex) { | ||||
|       throw die(ex.getMessage()); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private List<String> readSshKey(final List<String> sshKeys) | ||||
|       throws UnsupportedEncodingException, IOException { | ||||
|     if (!sshKeys.isEmpty()) { | ||||
|       String sshKey = ""; | ||||
|       int idx = sshKeys.indexOf("-"); | ||||
|       if (idx >= 0) { | ||||
|         sshKey = ""; | ||||
|         BufferedReader br = | ||||
|             new BufferedReader(new InputStreamReader(in, "UTF-8")); | ||||
|         String line; | ||||
|         while ((line = br.readLine()) != null) { | ||||
|           sshKey += line + "\n"; | ||||
|         } | ||||
|         sshKeys.set(idx, sshKey); | ||||
|       } | ||||
|     } | ||||
|     return sshKeys; | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user