Skip to content

Reroute cloud through IPC channel #10285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 13 commits into
base: master
Choose a base branch
from
Draft
1 change: 1 addition & 0 deletions localtypings/pxtarget.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ declare namespace pxt {
timeMachineDiffInterval?: number; // An interval in milliseconds at which to take diffs to store in project history. Defaults to 5 minutes
timeMachineSnapshotInterval?: number; // An interval in milliseconds at which to take full project snapshots in project history. Defaults to 15 minutes
adjustBlockContrast?: boolean; // If set to true, all block colors will automatically be adjusted to have a contrast ratio of 4.5 with text
ipcIdentityProxy?: boolean; // for use with the in game minecraft experience only. If true, proxies all identity API requests through the ipc channel
}

interface DownloadDialogTheme {
Expand Down
87 changes: 87 additions & 0 deletions localtypings/pxteditor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ declare namespace pxt.editor {
| "serviceworkerregistered"
| "runeval"
| "precachetutorial"
| "cloudproxy"
| "setcolorthemebyid"

// package extension messasges
Expand Down Expand Up @@ -1408,6 +1409,92 @@ declare namespace pxt.editor {

type AssetEditorEvent = AssetEditorRequestSaveEvent | AssetEditorReadyEvent;

type CloudProject = {
id: string;
shareId?: string;
header: string;
text: string;
version: string;

// minecraft specific
driveItemId?: string;
};

interface BaseCloudProxyRequest extends EditorMessageRequest {
action: "cloudproxy";
operation: string;
response: true;
}

interface CloudProxyUserRequest extends BaseCloudProxyRequest {
operation: "user";
}

interface CloudProxyListRequest extends BaseCloudProxyRequest {
operation: "list";
headerIds?: string[];
}

interface CloudProxyGetRequest extends BaseCloudProxyRequest {
operation: "get";
headerId: string;
}

interface CloudProxySetRequest extends BaseCloudProxyRequest {
operation: "set";
project: CloudProject;
}

interface CloudProxyDeleteRequest extends BaseCloudProxyRequest {
operation: "delete";
headerId: string;
}

type CloudProxyRequest =
| CloudProxyUserRequest
| CloudProxyListRequest
| CloudProxyGetRequest
| CloudProxySetRequest
| CloudProxyDeleteRequest;


interface BaseCloudProxyResponse extends EditorMessageResponse {
action: "cloudproxy";
operation: string;
resp: pxt.auth.ApiResult<any>;
}

interface CloudProxyUserResponse extends BaseCloudProxyResponse {
operation: "user";
}

interface CloudProxyListResponse extends BaseCloudProxyResponse {
operation: "list";
resp: pxt.auth.ApiResult<CloudProject[]>;
}

interface CloudProxyGetResponse extends BaseCloudProxyResponse {
operation: "get";
resp: pxt.auth.ApiResult<CloudProject>;
}

interface CloudProxySetResponse extends BaseCloudProxyResponse {
operation: "set";
resp: pxt.auth.ApiResult<string>;
}

interface CloudProxyDeleteResponse extends BaseCloudProxyResponse {
operation: "delete";
resp: pxt.auth.ApiResult<string>;
}

type CloudProxyResponse =
| CloudProxyUserResponse
| CloudProxyListResponse
| CloudProxyGetResponse
| CloudProxySetResponse
| CloudProxyDeleteResponse;

export interface TextEdit {
range: monaco.Range;
replacement: string;
Expand Down
12 changes: 12 additions & 0 deletions pxtlib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ namespace pxt.auth {
// Last known auth token state. This is provided as a convenience for legacy methods that cannot be made async.
// Preference hasAuthTokenAsync() over taking a dependency on this cached value.
export let cachedHasAuthToken = false;
export let cachedAuthOffline = false;

async function setLocalStorageValueAsync(key: string, value: string | undefined): Promise<void> {
if (!!value)
Expand All @@ -125,6 +126,10 @@ namespace pxt.auth {
return await setLocalStorageValueAsync(CSRF_TOKEN_KEY, token);
}
export async function hasAuthTokenAsync(): Promise<boolean> {
if (proxyIdentityThroughIPC()) {
cachedHasAuthToken = true;
return true;
}
return !!(await getAuthTokenAsync());
}
async function delAuthTokenAsync(): Promise<void> {
Expand Down Expand Up @@ -757,9 +762,16 @@ namespace pxt.auth {
}

export function hasIdentity(): boolean {
if (proxyIdentityThroughIPC()) {
return true;
}
return !authDisabled && !pxt.BrowserUtils.isPxtElectron() && identityProviders().length > 0;
}

export function proxyIdentityThroughIPC(): boolean {
return pxt.appTarget.appTheme.ipcIdentityProxy;
}

function idpEnabled(idp: pxt.IdentityProviderId): boolean {
return identityProviders().filter(prov => prov.id === idp).length > 0;
}
Expand Down
288 changes: 288 additions & 0 deletions webapp/public/cloudframe.html

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions webapp/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import { Tour } from "./components/onboarding/Tour";
import { parseTourStepsAsync } from "./onboarding";
import { initGitHubDb } from "./idbworkspace";
import { BlockDefinition, CategoryNameID } from "./toolbox";
import { MinecraftAuthClient } from "./minecraftAuthClient";
import { FeedbackModal } from "../../react-common/components/controls/Feedback/Feedback";
import { ThemeManager } from "../../react-common/components/theming/themeManager";

Expand Down Expand Up @@ -6082,6 +6083,10 @@ document.addEventListener("DOMContentLoaded", async () => {

initGitHubDb();

if (pxt.auth.proxyIdentityThroughIPC()) {
auth.overrideAuthClient(() => new MinecraftAuthClient());
}

// DO NOT put any async code before this line! The serviceworker must be initialized before
// the window load event fires
appcache.init(() => theEditor.reloadEditor());
Expand Down
17 changes: 15 additions & 2 deletions webapp/src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import * as core from "./core";
import * as data from "./data";
import * as cloud from "./cloud";
import * as workspace from "./workspace";
import { MinecraftAuthClient } from "./minecraftAuthClient";

/**
* Virtual API keys
*/
const MODULE = "auth";
const FIELD_USER_PROFILE = "profile";
const FIELD_LOGGED_IN = "logged-in";
const FIELD_OFFLINE = "offline";
export const USER_PROFILE = `${MODULE}:${FIELD_USER_PROFILE}`;
export const LOGGED_IN = `${MODULE}:${FIELD_LOGGED_IN}`;
export const OFFLINE = `${MODULE}:${FIELD_OFFLINE}`;

const USER_PREF_MODULE = "user-pref";
const FIELD_USER_PREFERENCES = "preferences";
Expand All @@ -37,7 +40,7 @@ export class Component<TProps, TState> extends data.Component<TProps, TState> {
}
}

class AuthClient extends pxt.auth.AuthClient {
export class AuthClient extends pxt.auth.AuthClient {
protected async onSignedIn(): Promise<void> {
const state = await pxt.auth.getUserStateAsync();
core.infoNotification(lf("Signed in: {0}", pxt.auth.userName(state.profile)));
Expand Down Expand Up @@ -98,6 +101,7 @@ class AuthClient extends pxt.auth.AuthClient {
switch (field) {
case FIELD_USER_PROFILE: return hasToken ? { ...state?.profile } : null;
case FIELD_LOGGED_IN: return hasToken && state?.profile != null;
case FIELD_OFFLINE: return pxt.auth.cachedAuthOffline;
}
return null;
}
Expand Down Expand Up @@ -156,12 +160,13 @@ function initVirtualApi() {
}

let authClientPromise: Promise<AuthClient>;
let authClientFactory = () => new AuthClient();

async function clientAsync(): Promise<AuthClient | undefined> {
if (!pxt.auth.hasIdentity()) { return undefined; }
if (authClientPromise) return authClientPromise;
authClientPromise = new Promise<AuthClient>(async (resolve, reject) => {
const cli = new AuthClient();
const cli = authClientFactory();
await cli.initAsync();
await cli.authCheckAsync();
await cli.initialUserPreferencesAsync();
Expand All @@ -170,6 +175,10 @@ async function clientAsync(): Promise<AuthClient | undefined> {
return authClientPromise;
}

export function overrideAuthClient(factory: () => AuthClient) {
authClientFactory = factory;
}

export function hasIdentity(): boolean {
return pxt.auth.hasIdentity();
}
Expand All @@ -178,6 +187,10 @@ export function loggedIn(): boolean {
return data.getData<boolean>(LOGGED_IN);
}

export function isOffline(): boolean {
return data.getData<boolean>(OFFLINE);
}

export function userProfile(): pxt.auth.UserProfile {
return data.getData<pxt.auth.UserProfile>(USER_PROFILE);
}
Expand Down
15 changes: 12 additions & 3 deletions webapp/src/cloud.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,17 @@ async function listAsync(hdrs?: Header[]): Promise<Header[]> {
header.cloudVersion = proj.version;
return header;
});

if (!hdrs) {

}
pxt.tickEvent(`identity.cloudApi.list.success`, { count: headers.length });
resolve(headers);
} else {
}
else if (result.statusCode === 404) {
resolve([]);
}
else {
pxt.tickEvent(`identity.cloudApi.list.failed`);
reject(result.err);
}
Expand Down Expand Up @@ -168,7 +176,7 @@ export class CloudTempMetadata {
const h = workspace.getHeader(this.headerId);
if (!h || !h.cloudUserId)
return undefined;
if (!auth.loggedIn())
if (!auth.loggedIn() || auth.isOffline())
return pxt.cloud.cloudStatus["offline"];
if (this._syncStartTime > 0)
return pxt.cloud.cloudStatus["syncing"];
Expand Down Expand Up @@ -421,8 +429,9 @@ async function syncAsyncInternal(opts: SyncAsyncOptions): Promise<pxt.workspace.

async function syncOneUp(local: Header): Promise<void> {
const projShorthand = shortName(local);
let cloudCurrent = local.cloudCurrent && (!fullSync || remoteHeaders.some(h => h.id === local.id))
try {
if (!local.cloudCurrent) {
if (!cloudCurrent) {
if (local.isDeleted) {
// Deleted local project, push to cloud
const res = await toCloud(local, null);
Expand Down
2 changes: 1 addition & 1 deletion webapp/src/headerbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export class HeaderBar extends data.Component<ISettingsProps, {}> {
const { home, header, tutorialOptions } = this.props.parent.state;
const isController = pxt.shell.isControllerMode();
const isNativeHost = cmds.isNativeHost();
const hasIdentity = auth.hasIdentity();
const hasIdentity = auth.hasIdentity() && !pxt.auth.proxyIdentityThroughIPC();
const activeEditor = this.props.parent.isPythonActive() ? "Python"
: (this.props.parent.isJavaScriptActive() ? "JavaScript" : "Blocks");

Expand Down
Loading