Automatically make first user account administrator
The first user to authenticate is now placed into the Administrators group, making it simpler to bootstrap the server by having at least one user who can modify permissions through the web UI, or create a Git repository over SSH. Change-Id: I8b39caaa129b3d0f693e0227fc3669ef18ca0df0 Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
parent
de98736af9
commit
82205a080f
|
@ -399,42 +399,10 @@ within the SSL enabled virtual host.
|
|||
Administrator Setup
|
||||
-------------------
|
||||
|
||||
Login to Gerrit through the web interface, so that a user account
|
||||
is initialized for you.
|
||||
|
||||
Add your newly created account to the "Administrators" group,
|
||||
so that you can manage the site through the web interface:
|
||||
|
||||
====
|
||||
INSERT INTO account_group_members
|
||||
(account_id, group_id)
|
||||
VALUES (
|
||||
(SELECT account_id FROM accounts
|
||||
WHERE preferred_email='you@example.com'),
|
||||
(SELECT admin_group_id FROM system_config)
|
||||
);
|
||||
====
|
||||
|
||||
You can also get your `account_id` from the web UI, under Settings,
|
||||
if you don't want to use a SELECT subquery above, or your email
|
||||
address wasn't prefilled automatically.
|
||||
|
||||
Group memberships are cached, so you need to either restart Gerrit,
|
||||
or try flushing the caches over SSH.
|
||||
|
||||
Since SSH cache flushing requires being in the "Administrators"
|
||||
group you may run into a chicken-and-egg problem, where you cannot
|
||||
flush the cache to make yourself an administrator because you are
|
||||
not yet an administrator. Therefore, restarting the application
|
||||
is the recommended bootstrap technique.
|
||||
|
||||
To flush the server's caches over SSH, ensure you have an SSH key
|
||||
(you can add one through the web UI under Settings, SSH Keys),
|
||||
and then run:
|
||||
|
||||
====
|
||||
ssh -p 29418 you@example.com gerrit flush-caches
|
||||
====
|
||||
Sign in to Gerrit through the web interface. The first user
|
||||
to register or sign-in will be automatically placed into the
|
||||
Administrators group. All subsequent users will be treated as
|
||||
unprivileged users.
|
||||
|
||||
|
||||
Project Setup
|
||||
|
|
|
@ -48,4 +48,6 @@ public interface AccountAccess extends Access<Account, Account.Id> {
|
|||
ResultSet<Account> suggestBySshUserName(String nameA, String nameB, int limit)
|
||||
throws OrmException;
|
||||
|
||||
@Query("LIMIT 1")
|
||||
ResultSet<Account> anyAccounts() throws OrmException;
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ package com.google.gerrit.server.account;
|
|||
import com.google.gerrit.common.auth.openid.OpenIdUrls;
|
||||
import com.google.gerrit.reviewdb.Account;
|
||||
import com.google.gerrit.reviewdb.AccountExternalId;
|
||||
import com.google.gerrit.reviewdb.AccountGroup;
|
||||
import com.google.gerrit.reviewdb.AccountGroupMember;
|
||||
import com.google.gerrit.reviewdb.AccountGroupMemberAudit;
|
||||
import com.google.gerrit.reviewdb.ReviewDb;
|
||||
import com.google.gerrit.server.config.AuthConfig;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
|
@ -28,6 +31,7 @@ import com.google.inject.Singleton;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/** Tracks authentication related details for user accounts. */
|
||||
@Singleton
|
||||
|
@ -37,16 +41,26 @@ public class AccountManager {
|
|||
private final AccountByEmailCache byEmailCache;
|
||||
private final AuthConfig authConfig;
|
||||
private final Realm realm;
|
||||
private final AtomicBoolean firstAccount;
|
||||
|
||||
@Inject
|
||||
AccountManager(final SchemaFactory<ReviewDb> schema,
|
||||
final AccountCache byIdCache, final AccountByEmailCache byEmailCache,
|
||||
final AuthConfig authConfig, final Realm accountMapper) {
|
||||
final AuthConfig authConfig, final Realm accountMapper)
|
||||
throws OrmException {
|
||||
this.schema = schema;
|
||||
this.byIdCache = byIdCache;
|
||||
this.byEmailCache = byEmailCache;
|
||||
this.authConfig = authConfig;
|
||||
this.realm = accountMapper;
|
||||
|
||||
firstAccount = new AtomicBoolean();
|
||||
final ReviewDb db = schema.open();
|
||||
try {
|
||||
firstAccount.set(db.accounts().anyAccounts().toList().isEmpty());
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,6 +260,20 @@ public class AccountManager {
|
|||
final Transaction txn = db.beginTransaction();
|
||||
db.accounts().insert(Collections.singleton(account), txn);
|
||||
db.accountExternalIds().insert(Collections.singleton(extId), txn);
|
||||
|
||||
if (firstAccount.get() && firstAccount.compareAndSet(true, false)) {
|
||||
// This is the first user account on our site. Assume this user
|
||||
// is going to be the site's administrator and just make them that
|
||||
// to bootstrap the authentication database.
|
||||
//
|
||||
final AccountGroup.Id admin = authConfig.getAdministratorsGroup();
|
||||
final AccountGroupMember m =
|
||||
new AccountGroupMember(new AccountGroupMember.Key(newId, admin));
|
||||
db.accountGroupMembers().insert(Collections.singleton(m), txn);
|
||||
db.accountGroupMembersAudit().insert(
|
||||
Collections.singleton(new AccountGroupMemberAudit(m, newId)), txn);
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
|
||||
byEmailCache.evict(account.getPreferredEmail());
|
||||
|
|
Loading…
Reference in New Issue