Merge changes I4fad66f5,I6ddb8258
* changes: Settings screen for OAuth tokens REST API for retrieving OAuth access tokens
This commit is contained in:
commit
4693626108
@ -420,6 +420,43 @@ Deletes the HTTP password of an account.
|
||||
HTTP/1.1 204 No Content
|
||||
----
|
||||
|
||||
[[get-oauth-token]]
|
||||
=== Get OAuth Access Token
|
||||
--
|
||||
'GET /accounts/link:#account-id[\{account-id\}]/oauthtoken'
|
||||
--
|
||||
|
||||
Returns a previously obtained OAuth access token.
|
||||
|
||||
.Request
|
||||
----
|
||||
GET /accounts/self/oauthtoken HTTP/1.1
|
||||
----
|
||||
|
||||
As a response, an link:#oauth-token-info[OAuthTokenInfo] entity is returned
|
||||
that describes the OAuth access token.
|
||||
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
)]}'
|
||||
{
|
||||
"username": "johndow",
|
||||
"resource_host": "gerrit.example.org",
|
||||
"access_token": "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOi",
|
||||
"provider_id": "oauth-plugin:oauth-provider",
|
||||
"expires_at": "922337203775807",
|
||||
"type": "bearer"
|
||||
}
|
||||
----
|
||||
|
||||
If there is no token available, or the token has already expired,
|
||||
"`404 Not Found`" is returned as response. Requests to obtain an access
|
||||
token of another user are rejected with "`403 Forbidden`".
|
||||
|
||||
[[list-account-emails]]
|
||||
=== List Account Emails
|
||||
--
|
||||
@ -2214,6 +2251,22 @@ If empty or not set and `generate` is false or not set, the HTTP
|
||||
password is deleted.
|
||||
|============================
|
||||
|
||||
[[oauth-token-info]]
|
||||
=== OAuthTokenInfo
|
||||
The `OAuthTokenInfo` entity contains information about an OAuth access token.
|
||||
|
||||
[options="header",cols="1,^1,5"]
|
||||
|========================
|
||||
|Field Name ||Description
|
||||
|`username` ||The owner of the OAuth access token.
|
||||
|`resource_host` ||The host of the Gerrit instance.
|
||||
|`access_token` ||The actual token value.
|
||||
|`provider_id` |optional|
|
||||
The identifier of the OAuth provider in the form `plugin-name:provider-name`.
|
||||
|`expires_at` |optional|Time of expiration of this token in milliseconds.
|
||||
|`type` ||The type of the OAuth access token, always `bearer`.
|
||||
|========================
|
||||
|
||||
[[preferences-info]]
|
||||
=== PreferencesInfo
|
||||
The `PreferencesInfo` entity contains information about a user's preferences.
|
||||
|
@ -29,6 +29,7 @@ public class PageLinks {
|
||||
public static final String SETTINGS_SSHKEYS = "/settings/ssh-keys";
|
||||
public static final String SETTINGS_GPGKEYS = "/settings/gpg-keys";
|
||||
public static final String SETTINGS_HTTP_PASSWORD = "/settings/http-password";
|
||||
public static final String SETTINGS_OAUTH_TOKEN = "/settings/oauth-token";
|
||||
public static final String SETTINGS_WEBIDENT = "/settings/web-identities";
|
||||
public static final String SETTINGS_MYGROUPS = "/settings/group-memberships";
|
||||
public static final String SETTINGS_AGREEMENTS = "/settings/agreements";
|
||||
|
@ -31,16 +31,23 @@ public class OAuthToken implements Serializable {
|
||||
*/
|
||||
private final long expiresAt;
|
||||
|
||||
/**
|
||||
* The identifier of the OAuth provider that issued this token
|
||||
* in the form <tt>"plugin-name:provider-name"</tt>, or {@code null}.
|
||||
*/
|
||||
private final String providerId;
|
||||
|
||||
public OAuthToken(String token, String secret, String raw) {
|
||||
this(token, secret, raw, Long.MAX_VALUE);
|
||||
this(token, secret, raw, Long.MAX_VALUE, null);
|
||||
}
|
||||
|
||||
public OAuthToken(String token, String secret, String raw,
|
||||
long expiresAt) {
|
||||
long expiresAt, String providerId) {
|
||||
this.token = token;
|
||||
this.secret = secret;
|
||||
this.raw = raw;
|
||||
this.expiresAt = expiresAt;
|
||||
this.providerId = providerId;
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
@ -62,4 +69,8 @@ public class OAuthToken implements Serializable {
|
||||
public boolean isExpired() {
|
||||
return System.currentTimeMillis() > expiresAt;
|
||||
}
|
||||
|
||||
public String getProviderId() {
|
||||
return providerId;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2016 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.client.info;
|
||||
|
||||
import com.google.gwt.core.client.JavaScriptObject;
|
||||
|
||||
|
||||
public class OAuthTokenInfo extends JavaScriptObject {
|
||||
|
||||
protected OAuthTokenInfo() {
|
||||
}
|
||||
|
||||
public final native String username() /*-{ return this.username; }-*/;
|
||||
public final native String resourceHost() /*-{ return this.resource_host; }-*/;
|
||||
public final native String accessToken() /*-{ return this.access_token; }-*/;
|
||||
public final native String providerId() /*-{ return this.provider_id; }-*/;
|
||||
public final native String expiresAt() /*-{ return this.expires_at; }-*/;
|
||||
public final native String type() /*-{ return this.type; }-*/;
|
||||
}
|
@ -33,6 +33,7 @@ import static com.google.gerrit.common.PageLinks.SETTINGS_EDIT_PREFERENCES;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_EXTENSION;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_GPGKEYS;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_HTTP_PASSWORD;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_OAUTH_TOKEN;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_MYGROUPS;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_NEW_AGREEMENT;
|
||||
import static com.google.gerrit.common.PageLinks.SETTINGS_PREFERENCES;
|
||||
@ -48,6 +49,7 @@ import com.google.gerrit.client.account.MyEditPreferencesScreen;
|
||||
import com.google.gerrit.client.account.MyGpgKeysScreen;
|
||||
import com.google.gerrit.client.account.MyGroupsScreen;
|
||||
import com.google.gerrit.client.account.MyIdentitiesScreen;
|
||||
import com.google.gerrit.client.account.MyOAuthTokenScreen;
|
||||
import com.google.gerrit.client.account.MyPasswordScreen;
|
||||
import com.google.gerrit.client.account.MyPreferencesScreen;
|
||||
import com.google.gerrit.client.account.MyProfileScreen;
|
||||
@ -568,6 +570,12 @@ public class Dispatcher {
|
||||
return new MyPasswordScreen();
|
||||
}
|
||||
|
||||
if (matchExact(SETTINGS_OAUTH_TOKEN, token)
|
||||
&& Gerrit.info().auth().isOAuth()
|
||||
&& Gerrit.info().auth().isGitBasicAuth()) {
|
||||
return new MyOAuthTokenScreen();
|
||||
}
|
||||
|
||||
if (matchExact(MY_GROUPS, token)
|
||||
|| matchExact(SETTINGS_MYGROUPS, token)) {
|
||||
return new MyGroupsScreen();
|
||||
|
@ -105,6 +105,14 @@ public interface GerritCss extends CssResource {
|
||||
String menuScreenMenuBar();
|
||||
String needsReview();
|
||||
String negscore();
|
||||
String oauthExpires();
|
||||
String oauthInfoBlock();
|
||||
String oauthPanel();
|
||||
String oauthPanelCookieEntry();
|
||||
String oauthPanelCookieHeading();
|
||||
String oauthPanelNetRCEntry();
|
||||
String oauthPanelNetRCHeading();
|
||||
String oauthToken();
|
||||
String pagingLink();
|
||||
String patchSetActions();
|
||||
String pluginProjectConfigInheritedValue();
|
||||
|
@ -57,6 +57,7 @@ public interface AccountConstants extends Constants {
|
||||
String tabGpgKeys();
|
||||
String tabHttpAccess();
|
||||
String tabMyGroups();
|
||||
String tabOAuthToken();
|
||||
String tabPreferences();
|
||||
String tabSshKeys();
|
||||
String tabWatchedProjects();
|
||||
@ -81,6 +82,12 @@ public interface AccountConstants extends Constants {
|
||||
String invalidUserName();
|
||||
String invalidUserEmail();
|
||||
|
||||
String labelOAuthToken();
|
||||
String labelOAuthExpires();
|
||||
String labelOAuthNetRCEntry();
|
||||
String labelOAuthGitCookie();
|
||||
String labelOAuthExpired();
|
||||
|
||||
String sshKeyInvalid();
|
||||
String sshKeyAlgorithm();
|
||||
String sshKeyKey();
|
||||
|
@ -44,6 +44,7 @@ tabDiffPreferences = Diff Preferences
|
||||
tabEditPreferences = Edit Preferences
|
||||
tabGpgKeys = GPG Public Keys
|
||||
tabHttpAccess = HTTP Password
|
||||
tabOAuthToken = OAuth Token
|
||||
tabMyGroups = Groups
|
||||
tabPreferences = Preferences
|
||||
tabSshKeys = SSH Public Keys
|
||||
@ -68,6 +69,13 @@ linkEditFullName = Edit
|
||||
linkReloadContact = Reload
|
||||
invalidUserName = Username must contain only letters, numbers, _, - or .
|
||||
invalidUserEmail = Email format is wrong.
|
||||
|
||||
labelOAuthToken = Access Token
|
||||
labelOAuthExpires = Expires
|
||||
labelOAuthNetRCEntry = Entry for ~/.netrc
|
||||
labelOAuthGitCookie = Entry for ~/.gitcookies
|
||||
labelOAuthExpired = To obtain an access token please sign out and sign in again.
|
||||
|
||||
sshKeyInvalid = Invalid Key
|
||||
sshKeyAlgorithm = Algorithm
|
||||
sshKeyKey = Key
|
||||
|
@ -0,0 +1,197 @@
|
||||
// Copyright (C) 2016 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.client.account;
|
||||
|
||||
import com.google.gerrit.client.Gerrit;
|
||||
import com.google.gerrit.client.info.GeneralPreferences;
|
||||
import com.google.gerrit.client.info.OAuthTokenInfo;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.rpc.ScreenLoadCallback;
|
||||
import com.google.gwt.i18n.client.DateTimeFormat;
|
||||
import com.google.gwt.i18n.client.LocaleInfo;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Grid;
|
||||
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwtexpui.clippy.client.CopyableLabel;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class MyOAuthTokenScreen extends SettingsScreen {
|
||||
private CopyableLabel tokenLabel;
|
||||
private Label expiresLabel;
|
||||
private Label expiredNote;
|
||||
private CopyableLabel netrcValue;
|
||||
private CopyableLabel cookieValue;
|
||||
private FlowPanel flow;
|
||||
private Grid grid;
|
||||
|
||||
@Override
|
||||
protected void onInitUI() {
|
||||
super.onInitUI();
|
||||
|
||||
tokenLabel = new CopyableLabel("");
|
||||
tokenLabel.addStyleName(Gerrit.RESOURCES.css().oauthToken());
|
||||
|
||||
expiresLabel = new Label("");
|
||||
expiresLabel.addStyleName(Gerrit.RESOURCES.css().oauthExpires());
|
||||
|
||||
grid = new Grid(2, 2);
|
||||
grid.setStyleName(Gerrit.RESOURCES.css().infoBlock());
|
||||
grid.addStyleName(Gerrit.RESOURCES.css().oauthInfoBlock());
|
||||
add(grid);
|
||||
|
||||
expiredNote = new Label(Util.C.labelOAuthExpired());
|
||||
expiredNote.setVisible(false);
|
||||
add(expiredNote);
|
||||
|
||||
row(grid, 0, Util.C.labelOAuthToken(), tokenLabel);
|
||||
row(grid, 1, Util.C.labelOAuthExpires(), expiresLabel);
|
||||
|
||||
CellFormatter fmt = grid.getCellFormatter();
|
||||
fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost());
|
||||
fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost());
|
||||
fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader());
|
||||
|
||||
flow = new FlowPanel();
|
||||
flow.setStyleName(Gerrit.RESOURCES.css().oauthPanel());
|
||||
add(flow);
|
||||
|
||||
Label netrcLabel = new Label(Util.C.labelOAuthNetRCEntry());
|
||||
netrcLabel.setStyleName(Gerrit.RESOURCES.css().oauthPanelNetRCHeading());
|
||||
flow.add(netrcLabel);
|
||||
netrcValue= new CopyableLabel("");
|
||||
netrcValue.setStyleName(Gerrit.RESOURCES.css().oauthPanelNetRCEntry());
|
||||
flow.add(netrcValue);
|
||||
|
||||
Label cookieLabel = new Label(Util.C.labelOAuthGitCookie());
|
||||
cookieLabel.setStyleName(Gerrit.RESOURCES.css().oauthPanelCookieHeading());
|
||||
flow.add(cookieLabel);
|
||||
cookieValue = new CopyableLabel("");
|
||||
cookieValue.setStyleName(Gerrit.RESOURCES.css().oauthPanelCookieEntry());
|
||||
flow.add(cookieValue);
|
||||
}
|
||||
|
||||
private void row(Grid grid, int row, String name, Widget field) {
|
||||
final CellFormatter fmt = grid.getCellFormatter();
|
||||
if (LocaleInfo.getCurrentLocale().isRTL()) {
|
||||
grid.setText(row, 1, name);
|
||||
grid.setWidget(row, 0, field);
|
||||
fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().header());
|
||||
} else {
|
||||
grid.setText(row, 0, name);
|
||||
grid.setWidget(row, 1, field);
|
||||
fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().header());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLoad() {
|
||||
super.onLoad();
|
||||
AccountApi.self().view("preferences")
|
||||
.get(new ScreenLoadCallback<GeneralPreferences>(this) {
|
||||
@Override
|
||||
protected void preDisplay(GeneralPreferences prefs) {
|
||||
display(prefs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void display(final GeneralPreferences prefs) {
|
||||
AccountApi.self().view("oauthtoken")
|
||||
.get(new GerritCallback<OAuthTokenInfo>() {
|
||||
@Override
|
||||
public void onSuccess(OAuthTokenInfo tokenInfo) {
|
||||
tokenLabel.setText(tokenInfo.accessToken());
|
||||
expiresLabel.setText(getExpiresAt(tokenInfo, prefs));
|
||||
netrcValue.setText(getNetRC(tokenInfo));
|
||||
cookieValue.setText(getCookie(tokenInfo));
|
||||
flow.setVisible(true);
|
||||
expiredNote.setVisible(false);
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Throwable caught) {
|
||||
if (isNoSuchEntity(caught) || isSigninFailure(caught)) {
|
||||
tokenLabel.setText("");
|
||||
expiresLabel.setText("");
|
||||
netrcValue.setText("");
|
||||
cookieValue.setText("");
|
||||
flow.setVisible(false);
|
||||
expiredNote.setVisible(true);
|
||||
} else {
|
||||
showFailure(caught);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static long getExpiresAt(OAuthTokenInfo tokenInfo) {
|
||||
if (tokenInfo.expiresAt() == null) {
|
||||
return Long.MAX_VALUE;
|
||||
}
|
||||
long expiresAt;
|
||||
try {
|
||||
expiresAt = Long.parseLong(tokenInfo.expiresAt());
|
||||
} catch (NumberFormatException e) {
|
||||
return Long.MAX_VALUE;
|
||||
}
|
||||
return expiresAt;
|
||||
}
|
||||
|
||||
private static long getExpiresAtSeconds(OAuthTokenInfo tokenInfo) {
|
||||
return getExpiresAt(tokenInfo) / 1000L;
|
||||
}
|
||||
|
||||
private static String getExpiresAt(OAuthTokenInfo tokenInfo,
|
||||
GeneralPreferences prefs) {
|
||||
long expiresAt = getExpiresAt(tokenInfo);
|
||||
if (expiresAt == Long.MAX_VALUE) {
|
||||
return "";
|
||||
}
|
||||
String dateFormat = prefs.dateFormat().getLongFormat();
|
||||
String timeFormat = prefs.timeFormat().getFormat();
|
||||
DateTimeFormat formatter = DateTimeFormat.getFormat(
|
||||
dateFormat + " " + timeFormat);
|
||||
return formatter.format(new Date(expiresAt));
|
||||
}
|
||||
|
||||
private static String getNetRC(OAuthTokenInfo accessTokenInfo) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("machine ");
|
||||
sb.append(accessTokenInfo.resourceHost());
|
||||
sb.append(" login ");
|
||||
sb.append(accessTokenInfo.username());
|
||||
sb.append(" password ");
|
||||
sb.append(accessTokenInfo.accessToken());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String getCookie(OAuthTokenInfo accessTokenInfo) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(accessTokenInfo.resourceHost());
|
||||
sb.append("\tFALSE\t/\tTRUE\t");
|
||||
sb.append(getExpiresAtSeconds(accessTokenInfo));
|
||||
sb.append("\tgit-");
|
||||
sb.append(accessTokenInfo.username());
|
||||
sb.append('\t');
|
||||
sb.append(accessTokenInfo.accessToken());
|
||||
if (accessTokenInfo.providerId() != null) {
|
||||
sb.append('@').append(accessTokenInfo.providerId());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
@ -47,6 +47,10 @@ public abstract class SettingsScreen extends MenuScreen {
|
||||
if (Gerrit.info().auth().isHttpPasswordSettingsEnabled()) {
|
||||
linkByGerrit(Util.C.tabHttpAccess(), PageLinks.SETTINGS_HTTP_PASSWORD);
|
||||
}
|
||||
if (Gerrit.info().auth().isOAuth()
|
||||
&& Gerrit.info().auth().isGitBasicAuth()) {
|
||||
linkByGerrit(Util.C.tabOAuthToken(), PageLinks.SETTINGS_OAUTH_TOKEN);
|
||||
}
|
||||
if (Gerrit.info().gerrit().editGpgKeys()) {
|
||||
linkByGerrit(Util.C.tabGpgKeys(), PageLinks.SETTINGS_GPGKEYS);
|
||||
}
|
||||
|
@ -828,6 +828,70 @@ a:hover.downloadLink {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.oauthInfoBlock {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.oauthToken {
|
||||
font-family: monospace;
|
||||
font-size: small;
|
||||
width: 40em;
|
||||
}
|
||||
.oauthToken span {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 38em;
|
||||
}
|
||||
.oauthExpires {
|
||||
font-family: monospace;
|
||||
font-size: small;
|
||||
width: 40em;
|
||||
}
|
||||
.oauthPanel {
|
||||
margin-top: 10px;
|
||||
border: 1px solid trimColor;
|
||||
padding: 5px 5px 5px 5px;
|
||||
}
|
||||
.oauthPanelNetRCHeading {
|
||||
margin-top: 5px;
|
||||
margin-left: 1em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.oauthPanelNetRCEntry {
|
||||
margin-top: 5px;
|
||||
margin-left: 2em;
|
||||
font-family: monospace;
|
||||
font-size: small;
|
||||
width: 80em;
|
||||
}
|
||||
.oauthPanelNetRCEntry span {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 78em;
|
||||
}
|
||||
.oauthPanelCookieHeading {
|
||||
margin-top: 15px;
|
||||
margin-left: 1em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.oauthPanelCookieEntry {
|
||||
margin-top: 5px;
|
||||
margin-left: 2em;
|
||||
font-family: monospace;
|
||||
font-size: small;
|
||||
width: 80em;
|
||||
}
|
||||
.oauthPanelCookieEntry span {
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 78em;
|
||||
}
|
||||
|
||||
|
||||
/** CommentedActionDialog **/
|
||||
.commentedActionDialog .gwt-DisclosurePanel .header td {
|
||||
|
@ -0,0 +1,90 @@
|
||||
// Copyright (C) 2016 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.server.account;
|
||||
|
||||
import com.google.gerrit.extensions.auth.oauth.OAuthToken;
|
||||
import com.google.gerrit.extensions.restapi.AuthException;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.auth.oauth.OAuthTokenCache;
|
||||
import com.google.gerrit.server.config.CanonicalWebUrl;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
@Singleton
|
||||
class GetOAuthToken implements RestReadView<AccountResource>{
|
||||
|
||||
private static final String BEARER_TYPE = "bearer";
|
||||
|
||||
private final Provider<CurrentUser> self;
|
||||
private final OAuthTokenCache tokenCache;
|
||||
private final String hostName;
|
||||
|
||||
@Inject
|
||||
GetOAuthToken(Provider<CurrentUser> self,
|
||||
OAuthTokenCache tokenCache,
|
||||
@CanonicalWebUrl Provider<String> urlProvider) {
|
||||
this.self = self;
|
||||
this.tokenCache = tokenCache;
|
||||
this.hostName = getHostName(urlProvider.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuthTokenInfo apply(AccountResource rsrc) throws AuthException,
|
||||
ResourceNotFoundException {
|
||||
if (self.get() != rsrc.getUser()) {
|
||||
throw new AuthException("not allowed to get access token");
|
||||
}
|
||||
String username = rsrc.getUser().getAccount().getUserName();
|
||||
if (username == null) {
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
OAuthToken accessToken = tokenCache.get(username);
|
||||
if (accessToken == null) {
|
||||
throw new ResourceNotFoundException();
|
||||
}
|
||||
OAuthTokenInfo accessTokenInfo = new OAuthTokenInfo();
|
||||
accessTokenInfo.username = username;
|
||||
accessTokenInfo.resourceHost = hostName;
|
||||
accessTokenInfo.accessToken = accessToken.getToken();
|
||||
accessTokenInfo.providerId = accessToken.getProviderId();
|
||||
accessTokenInfo.expiresAt = Long.toString(accessToken.getExpiresAt());
|
||||
accessTokenInfo.type = BEARER_TYPE;
|
||||
return accessTokenInfo;
|
||||
}
|
||||
|
||||
private static String getHostName(String canonicalWebUrl) {
|
||||
try {
|
||||
return new URI(canonicalWebUrl).getHost();
|
||||
} catch (URISyntaxException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OAuthTokenInfo {
|
||||
public String username;
|
||||
public String resourceHost;
|
||||
public String accessToken;
|
||||
public String providerId;
|
||||
public String expiresAt;
|
||||
public String type;
|
||||
}
|
||||
|
||||
}
|
@ -66,6 +66,8 @@ public class Module extends RestApiModule {
|
||||
get(SSH_KEY_KIND).to(GetSshKey.class);
|
||||
delete(SSH_KEY_KIND).to(DeleteSshKey.class);
|
||||
|
||||
get(ACCOUNT_KIND, "oauthtoken").to(GetOAuthToken.class);
|
||||
|
||||
get(ACCOUNT_KIND, "avatar").to(GetAvatar.class);
|
||||
get(ACCOUNT_KIND, "avatar.change.url").to(GetAvatarChangeUrl.class);
|
||||
|
||||
|
@ -128,6 +128,7 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
|
||||
info.useContributorAgreements = toBoolean(cfg.isUseContributorAgreements());
|
||||
info.editableAccountFields = new ArrayList<>(realm.getEditableFields());
|
||||
info.switchAccountUrl = cfg.getSwitchAccountUrl();
|
||||
info.isGitBasicAuth = toBoolean(cfg.isGitBasicAuth());
|
||||
|
||||
switch (info.authType) {
|
||||
case LDAP:
|
||||
@ -135,7 +136,6 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
|
||||
info.registerUrl = cfg.getRegisterUrl();
|
||||
info.registerText = cfg.getRegisterText();
|
||||
info.editFullNameUrl = cfg.getEditFullNameUrl();
|
||||
info.isGitBasicAuth = toBoolean(cfg.isGitBasicAuth());
|
||||
break;
|
||||
|
||||
case CUSTOM_EXTENSION:
|
||||
|
Loading…
Reference in New Issue
Block a user