Skip to content

Commit

Permalink
Merge pull request #2305 from uProxy/dborkan-cloud-invites
Browse files Browse the repository at this point in the history
Add newly deployed cloud friend to roster
  • Loading branch information
dborkan committed Mar 16, 2016
2 parents 23f76f6 + 626f370 commit 503e5e4
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 34 deletions.
57 changes: 52 additions & 5 deletions src/generic_core/uproxy_core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ export class uProxyCore implements uproxy_core_api.CoreApi {
ui.update(uproxy_core_api.Update.CORE_UPDATE_AVAILABLE, details);
}

public cloudInstall = (args:uproxy_core_api.CloudInstallArgs): Promise<uproxy_core_api.CloudInstallResult> => {
public cloudInstall = (args:uproxy_core_api.CloudInstallArgs): Promise<void> => {
if (args.providerName !== 'digitalocean') {
return Promise.reject(new Error('unsupported cloud provider'));
}
Expand Down Expand Up @@ -655,15 +655,62 @@ export class uProxyCore implements uproxy_core_api.CoreApi {
};
const MAX_INSTALLS = 5;
return retry(install, MAX_INSTALLS);
}).then((output: string) => {
}).then((cloudNetworkData :any) => {
// TODO: make cloudNetworkData an Invite type. This requires the cloud
// social provider to export the Invite interface, and also to cleanup
// reference paths so that uProxy doesn't need to include modules like
// ssh2.
destroyModules();
return <uproxy_core_api.CloudInstallResult>{
invite: output
};

// Login to the Cloud network if the user isn't already so that
// we can add the new cloud server to the roster.
return this.loginIfNeeded_('Cloud').then((cloudNetwork) => {
// Set flag so Cloud social provider knows this invite is for the admin
// user, who just created the server.
cloudNetworkData['isAdmin'] = true;

// Synthesize an invite token based on cloudNetworkData.
// CONSIDER: if we had a social.acceptInvitation that only took
// networkData we wouldn't need to fake the other fields.
return cloudNetwork.acceptInvitation({
v: 2,
networkName: 'Cloud',
userName: cloudNetworkData['host'],
networkData: JSON.stringify(cloudNetworkData)
});
});
}, (e: Error) => {
destroyModules();
return Promise.reject(e);
});
} // end of cloudInstall

// Gets a social.Network, and logs the user in if they aren't yet logged in.
private loginIfNeeded_ = (networkName :string) : Promise<social.Network> => {
let network = this.getNetworkByName_(networkName);
if (network) {
return Promise.resolve(network);
}

// User is not yet logged in.
return this.login({
network: networkName,
loginType: uproxy_core_api.LoginType.INITIAL
}).then(() => {
return this.getNetworkByName_(networkName);
});
}

// The social_network module in theory should support multiple userIds
// being logged into the same network. However that has never been tested
// and is not used by the rest of uProxy code. This method just returns
// the first (and currently only) network for the given networkName, or null
// if the network is not logged in.
private getNetworkByName_ = (networkName :string) : social.Network => {
for (var userId in social_network.networks[networkName]) {
return social_network.networks[networkName][userId];
}
return null;
}

public updateOrgPolicy(policy :Object) :void {
Expand Down
10 changes: 1 addition & 9 deletions src/generic_ui/polymer/cloud-install.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<link rel='import' href='../../bower/core-overlay/core-overlay.html'>
<link rel='import' href='../../bower/core-signals/core-signals.html'>
<link rel='import' href='../../bower/paper-input/paper-input-decorator.html'>
<link rel='import' href='../../bower/paper-progress/paper-progress.html'>
<link rel='import' href='../../bower/paper-radio-button/paper-radio-button.html'>
<link rel='import' href='../../bower/paper-radio-group/paper-radio-group.html'>
Expand Down Expand Up @@ -100,14 +99,7 @@ <h1>Create a cloud server</h1>

<uproxy-dialog layered='false' backdrop='true' id='successDialog'>
<h1>Create a cloud server</h1>
<p>Your cloud server is ready!</p>
<p>Below is the URL to administer your new server. Copy and paste it into a file and save it somewhere you'll be able to get to it in the future. Think of it as a password: keep it safe and don't share it with anyone you don't trust.</p>
<p>Once you've saved the URL, open it in your browser to add your new server to your contacts list.</p>
<div>
<paper-input-decorator layout vertical>
<input readonly is='core-input' on-tap='{{ select }}' value='{{ inviteUrl }}' />
</paper-input-decorator>
</div>
<p>Your cloud server is ready and has been added to your friends list.</p>
<uproxy-button on-tap='{{ closeDialogs }}'>{{ 'OK' | $$ }}</uproxy-button>
</uproxy-dialog>

Expand Down
8 changes: 1 addition & 7 deletions src/generic_ui/polymer/cloud-install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,15 @@ Polymer({
},
loginTapped: function() {
this.closeDialogs();
// TODO: show the dialog when this value changes, not this nasty hack
ui.cloudInstallStatus = '';
this.$.installingDialog.open();

ui.cloudInstall({
providerName: DEFAULT_PROVIDER,
region: this.$.regionMenu.selected
}).then((result: uproxy_core_api.CloudInstallResult) => {
this.inviteUrl = result.invite;
}).then(() => {
this.closeDialogs();
this.$.successDialog.open();

// TODO: In addition to displaying the URL so the user can store it somewhere
// we should add the new server to the user's contact list.
}).catch((e: Error) => {
// TODO: Figure out which fields in e are set, because message isn't.
this.closeDialogs();
Expand All @@ -47,6 +42,5 @@ Polymer({
},
ready: function() {
this.ui = ui;
this.inviteUrl = '';
}
});
4 changes: 2 additions & 2 deletions src/generic_ui/scripts/core_connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ class CoreConnector implements uproxy_core_api.CoreApi {
return this.promiseCommand(uproxy_core_api.Command.ACCEPT_INVITATION, data);
}

cloudInstall = (args:uproxy_core_api.CloudInstallArgs): Promise<uproxy_core_api.CloudInstallResult> => {
return this.promiseCommand(uproxy_core_api.Command.CLOUD_INSTALL, args);
cloudInstall = (args:uproxy_core_api.CloudInstallArgs): Promise<void> => {
return this.promiseCommand(uproxy_core_api.Command.CLOUD_INSTALL, args);
}
} // class CoreConnector

Expand Down
3 changes: 1 addition & 2 deletions src/generic_ui/scripts/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,6 @@ export class UserInterface implements ui_constants.UiApi {
// Update the user's category in both get and share tabs.
model.categorizeUser(user, this.model.contacts.getAccessContacts,
oldUserCategories.getTab, newUserCategories.getTab);

if (user.status != social.UserStatus.CLOUD_INSTANCE_SHARED_WITH_LOCAL) {
model.categorizeUser(user, this.model.contacts.shareAccessContacts,
oldUserCategories.shareTab, newUserCategories.shareTab);
Expand Down Expand Up @@ -1353,7 +1352,7 @@ export class UserInterface implements ui_constants.UiApi {
return i18nMessage.replace(/<((?!(\/?(strong|a|p|br|uproxy-faq-link)))[^>]+)>/g, '');
}

public cloudInstall = (args:uproxy_core_api.CloudInstallArgs): Promise<uproxy_core_api.CloudInstallResult> => {
public cloudInstall = (args:uproxy_core_api.CloudInstallArgs): Promise<void> => {
return this.core.cloudInstall(args);
}
} // class UserInterface
10 changes: 1 addition & 9 deletions src/interfaces/uproxy_core_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ export enum Update {
PORT_CONTROL_STATUS = 2025,
// Payload is a string, obtained from the SignalBatcher in uproxy-lib.
ONETIME_MESSAGE = 2026,
// Payload is a CloudInstallResult.
CLOUD_INSTALL_STATUS = 2027
}

Expand Down Expand Up @@ -224,13 +223,6 @@ export interface CloudInstallArgs {
region: string;
};

// Output of #cloudInstall.
export interface CloudInstallResult {
// Invitation URL, iff the the server was successfully created
// and provisioned.
invite: string;
};

/**
* The primary interface to the uProxy Core.
*
Expand Down Expand Up @@ -297,6 +289,6 @@ export interface CoreApi {
// callers should expose CLOUD_INSTALL_STATUS updates to the user.
// This may also invoke an OAuth flow, in order to perform operations
// with the cloud computing provider on the user's behalf.
cloudInstall(args:CloudInstallArgs): Promise<CloudInstallResult>;
cloudInstall(args:CloudInstallArgs): Promise<void>;
}

0 comments on commit 503e5e4

Please sign in to comment.