Skip to content

Commit ba86047

Browse files
Sentiausclaude
andcommitted
feat: add RolesAllowed to Drive token/connect endpoints and handle invalid_grant reauth
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 609316b commit ba86047

5 files changed

Lines changed: 9615 additions & 19078 deletions

File tree

amber/src/main/scala/org/apache/texera/web/resource/auth/GoogleDriveAuthResource.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,14 @@ import org.apache.texera.web.resource.auth.GoogleDriveAuthResource._
2626
import org.apache.texera.dao.jooq.generated.tables.daos.UserDao
2727
import org.apache.texera.dao.SqlServer
2828
import org.apache.texera.config.UserSystemConfig
29-
import org.apache.texera.auth.JwtAuth.{jwtClaims, TOKEN_EXPIRE_TIME_IN_MINUTES}
29+
import org.apache.texera.auth.JwtAuth.{TOKEN_EXPIRE_TIME_IN_MINUTES, jwtClaims}
3030
import org.apache.texera.auth.JwtAuth
31-
import com.google.api.client.googleapis.auth.oauth2.{GoogleRefreshTokenRequest,
32-
GoogleAuthorizationCodeTokenRequest,
33-
GoogleTokenResponse,
34-
GoogleAuthorizationCodeRequestUrl}
31+
import com.google.api.client.googleapis.auth.oauth2.{GoogleAuthorizationCodeRequestUrl, GoogleAuthorizationCodeTokenRequest, GoogleRefreshTokenRequest, GoogleTokenResponse}
3532
import com.google.api.client.auth.oauth2.TokenResponseException
3633
import com.google.api.client.http.javanet.NetHttpTransport
3734
import com.google.api.client.json.gson.GsonFactory
3835

36+
import javax.annotation.security.RolesAllowed
3937
import javax.ws.rs._
4038
import javax.ws.rs.core.MediaType
4139
import javax.ws.rs.core.Response
@@ -66,6 +64,7 @@ class GoogleDriveAuthResource extends LazyLogging {
6664

6765
@GET
6866
@Path("/token")
67+
@RolesAllowed(Array("REGULAR", "ADMIN"))
6968
def getDriveAccessToken(@Auth sessionUser: SessionUser): Response = {
7069
val user = userDao.fetchOneByUid(sessionUser.getUid)
7170
val refreshToken = user.getGoogleDriveRefreshToken
@@ -145,6 +144,7 @@ class GoogleDriveAuthResource extends LazyLogging {
145144

146145
@GET
147146
@Path("/connect")
147+
@RolesAllowed(Array("REGULAR", "ADMIN"))
148148
def getOAuth(
149149
@Auth sessionUser: SessionUser,
150150
@QueryParam("reauth") @DefaultValue("false") reauth: Boolean

frontend/src/app/dashboard/component/user/list-item/list-item.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export class ListItemComponent implements OnChanges, OnInit {
119119
private _entry?: DashboardEntry;
120120
hovering: boolean = false;
121121
isDriveConnected = false;
122+
driveNeedsReauth = false;
122123
exportMenuVisible = false;
123124

124125
@Input()
@@ -156,6 +157,7 @@ export class ListItemComponent implements OnChanges, OnInit {
156157
.pipe(untilDestroyed(this))
157158
.subscribe(res => {
158159
this.isDriveConnected = res.status === "ok";
160+
this.driveNeedsReauth = res.status === "invalid_grant";
159161
});
160162
this.driveService
161163
.onConnected()
@@ -286,7 +288,7 @@ export class ListItemComponent implements OnChanges, OnInit {
286288

287289
public onClickDriveAction(): void {
288290
if (!this.isDriveConnected) {
289-
this.driveService.connect();
291+
this.driveService.connect(this.driveNeedsReauth);
290292
return;
291293
}
292294
if (!this.entry.id) return;

frontend/src/app/dashboard/component/user/user-dataset/user-dataset-explorer/dataset-detail.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ export class DatasetDetailComponent implements OnInit {
155155
public viewCount: number = 0;
156156
public displayPreciseViewCount = false;
157157
public isDriveConnected = false;
158+
public driveNeedsReauth = false;
158159
public fileExportMenuVisible = false;
159160
public versionExportMenuVisible = false;
160161

@@ -268,6 +269,7 @@ export class DatasetDetailComponent implements OnInit {
268269
.pipe(untilDestroyed(this))
269270
.subscribe(res => {
270271
this.isDriveConnected = res.status === "ok";
272+
this.driveNeedsReauth = res.status === "invalid_grant";
271273
});
272274
this.driveService
273275
.onConnected()
@@ -304,7 +306,7 @@ export class DatasetDetailComponent implements OnInit {
304306

305307
public onClickDriveExportVersion(): void {
306308
if (!this.isDriveConnected) {
307-
this.driveService.connect();
309+
this.driveService.connect(this.driveNeedsReauth);
308310
return;
309311
}
310312
if (!this.did || !this.selectedVersion?.dvid) return;
@@ -321,7 +323,7 @@ export class DatasetDetailComponent implements OnInit {
321323

322324
public onClickDriveExportFile(): void {
323325
if (!this.isDriveConnected) {
324-
this.driveService.connect();
326+
this.driveService.connect(this.driveNeedsReauth);
325327
return;
326328
}
327329
if (!this.currentDisplayedFileName) return;

frontend/src/app/workspace/component/menu/menu.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ export class MenuComponent implements OnInit, OnDestroy {
137137
public isExportDeactivate: boolean = false;
138138
public showRegion: boolean = false;
139139
public isDriveConnected = false;
140+
public driveNeedsReauth = false;
140141
public exportMenuVisible = false;
141142
public showGrid: boolean = false;
142143
public showNumWorkers: boolean = false;
@@ -260,6 +261,7 @@ export class MenuComponent implements OnInit, OnDestroy {
260261
.pipe(untilDestroyed(this))
261262
.subscribe(res => {
262263
this.isDriveConnected = res.status === "ok";
264+
this.driveNeedsReauth = res.status === "invalid_grant";
263265
});
264266
this.driveService
265267
.onConnected()
@@ -672,7 +674,7 @@ export class MenuComponent implements OnInit, OnDestroy {
672674

673675
public onClickDriveExportWorkflow(): void {
674676
if (!this.isDriveConnected) {
675-
this.driveService.connect();
677+
this.driveService.connect(this.driveNeedsReauth);
676678
return;
677679
}
678680
const workflowContent: WorkflowContent = this.workflowActionService.getWorkflowContent();

0 commit comments

Comments
 (0)