Skip to content

Commit

Permalink
[ENG-5168] User addon credentials (#2183)
Browse files Browse the repository at this point in the history
-   Ticket: [ENG-5168]
-   Feature flag: 'gravy_waffle'

## Purpose
- Allow users to add new addon accounts in their user settings page

## Summary of Changes
- Make node argument optional for Provider class
- Update user-addons-manager to handle auth workflows
- Update external-service models
- Update user-settings addon page to allow for auth workflows
  • Loading branch information
futa-ikeda authored Apr 4, 2024
1 parent ed5d16f commit 96fa288
Show file tree
Hide file tree
Showing 15 changed files with 276 additions and 129 deletions.
4 changes: 2 additions & 2 deletions app/models/external-citation-service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { attr } from '@ember-data/model';

import OsfModel from './osf-model';
import { CredentialsFormat, ExternalServiceLinks } from './external-storage-service';
import { CredentialsFormat } from './external-storage-service';

export default class ExternalCitationServiceModel extends OsfModel {
@attr('fixstring') name!: string;
@attr('links') links!: ExternalServiceLinks;
@attr('string') iconUrl!: string;
@attr('string') credentialsFormat!: CredentialsFormat;
// TODO: actually need some attrs here for citation service options
}
Expand Down
4 changes: 2 additions & 2 deletions app/models/external-computing-service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { attr } from '@ember-data/model';

import OsfModel from './osf-model';
import { CredentialsFormat, ExternalServiceLinks } from './external-storage-service';
import { CredentialsFormat } from './external-storage-service';

export default class ExternalComputingServiceModel extends OsfModel {
@attr('fixstring') name!: string;
@attr('links') links!: ExternalServiceLinks;
@attr('string') iconUrl!: string;
@attr('string') credentialsFormat!: CredentialsFormat;
// TODO: actually need some attrs here for cloud computing options
}
Expand Down
8 changes: 2 additions & 6 deletions app/models/external-storage-service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { attr } from '@ember-data/model';

import OsfModel, { OsfLinks } from './osf-model';
import OsfModel from './osf-model';

export enum CredentialsFormat {
OAUTH = 'oauth',
Expand All @@ -11,14 +11,10 @@ export enum CredentialsFormat {
ACCESS_SECRET_KEYS = 'access_secret_keys',
}

export interface ExternalServiceLinks extends OsfLinks {
icon: string;
}

export default class ExternalStorageServiceModel extends OsfModel {
@attr('fixstring') name!: string;
@attr('object') links!: ExternalServiceLinks;
@attr('string') credentialsFormat!: CredentialsFormat;
@attr('string') iconUrl!: string;
// TODO: combine these boolean scopes into a single array of strings from some enum
@attr('boolean') readOnly!: boolean;
@attr('boolean') supportsCopy!: boolean;
Expand Down
26 changes: 15 additions & 11 deletions app/packages/addons-service/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,18 @@ interface ProviderTypeMapper {


export default class Provider {
@tracked node: NodeModel;
@tracked node?: NodeModel;
@tracked serviceNode?: ResourceReferenceModel;

currentUser: CurrentUserService;
@tracked userReference!: UserReferenceModel;
provider: AllProviderTypes;
providerMap?: ProviderTypeMapper;

get name() {
return this.provider.name;
}

providerTypeMapper: Record<string, ProviderTypeMapper> = {
externalStorageService: {
getConfiguredAddon: taskFor(this.getConfiguredStorageAddon),
Expand Down Expand Up @@ -83,8 +87,8 @@ export default class Provider {
return Boolean(this.configuredAddon);
}

constructor(provider: any, currentUser: CurrentUserService, node: NodeModel) {
setOwner(this, getOwner(node));
constructor(provider: any, currentUser: CurrentUserService, node?: NodeModel) {
setOwner(this, getOwner(provider));
this.node = node;
this.currentUser = currentUser;
this.provider = provider;
Expand Down Expand Up @@ -121,11 +125,13 @@ export default class Provider {
@task
@waitFor
async getResourceReference() {
const serviceNode = this.store.peekRecord('resource-reference', this.node.id);
if (serviceNode) {
this.serviceNode = serviceNode;
} else {
this.serviceNode = await this.store.findRecord('resource-reference', this.node.id);
if (this.node) {
const serviceNode = this.store.peekRecord('resource-reference', this.node.id);
if (serviceNode) {
this.serviceNode = serviceNode;
} else {
this.serviceNode = await this.store.findRecord('resource-reference', this.node.id);
}
}
}

Expand Down Expand Up @@ -191,9 +197,7 @@ export default class Provider {
@task
@waitFor
async getAuthorizedAccounts(accountType: RelationshipsFor<UserReferenceModel>, filter: any) {
if (this.userReference){
this.authorizedAccounts = await this.userReference.queryHasMany(accountType, filter);
}
this.authorizedAccounts = await this.userReference.queryHasMany(accountType, filter);
}

async userAddonAccounts() {
Expand Down
15 changes: 14 additions & 1 deletion app/settings/addons/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@
}
}

.disconnect-button {
.provider-list-wrapper {
flex-grow: 1;
}

.provider-list-item {
margin: 15px 10px;
border-bottom: solid 1px $color-border-gray;

&:first-child {
border-top: solid 1px $color-border-gray;
}
}

.float-right {
float: right;
}
144 changes: 97 additions & 47 deletions app/settings/addons/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,57 +5,107 @@
{{#if manager.currentListIsLoading}}
<LoadingIndicator @dark={{true}} />
{{else}}
<div local-class='addons-list-wrapper {{if this.isMobile 'mobile'}}'>
<div
data-analytics-scope='Addon List Filter'
local-class='filter-wrapper {{if this.isMobile 'mobile'}}'
{{#if manager.selectedProvider}}
<Button
data-test-cancel-account-setup
data-analytics-name='Cancel Account Setup'
local-class='float-right'
@layout='fake-link'
{{on 'click' manager.cancelAccountSetup}}
>
<Input
data-test-user-addon-list-filter-input
placeholder={{t 'addons.list.filter-placeholder'}}
@type='text'
@value={{manager.filterText}}
{{t 'general.back'}}
</Button>
{{#if (eq manager.pageMode 'terms')}}
<h3 local-class='page-heading'>
{{t 'addons.terms.heading' providerName=manager.selectedProvider.provider.name}}
</h3>
<Button
{{on 'click' manager.acceptProviderTerms}}
>
{{t 'general.ok'}}
</Button>
{{else if (eq manager.pageMode 'accountCreate')}}
<h3 local-class='page-heading'>
{{t 'addons.accountSelect.new-account'}}
</h3>
<AddonsService::AccountSetupManager
@provider={{manager.selectedProvider.provider}}
@manager={{manager}}
@onConnect={{manager.connectAccount}}
@onInput={{manager.onCredentialsInput}}
/>
{{#each manager.possibleFilterTypes as |type|}}
<Button
data-test-user-addon-list-filter={{type}}
data-analytics-name={{t (concat 'addons.list.filter.' type)}}
local-class='filter-button {{if (eq manager.activeFilterType type) 'active'}}'
@layout='fake-link'
{{on 'click' (fn manager.filterByAddonType type)}}
>
{{t (concat 'addons.list.filter.' type)}}
</Button>
{{/each}}
{{/if}}
{{else}}
<div
data-analytics-scope='Addon List'
local-class='addons-list-wrapper'
>
<div
data-analytics-scope='Addon List Filter'
local-class='filter-wrapper {{if this.isMobile 'mobile'}}'
>
<Input
data-test-user-addon-list-filter-input
placeholder={{t 'addons.list.filter-placeholder'}}
@type='text'
@value={{manager.filterText}}
/>
{{#each manager.possibleFilterTypes as |type|}}
<Button
data-test-user-addon-list-filter={{type}}
data-analytics-name={{t (concat 'addons.list.filter.' type)}}
local-class='filter-button {{if (eq manager.activeFilterType type) 'active'}}'
@layout='fake-link'
{{on 'click' (fn manager.filterByAddonType type)}}
>
{{t (concat 'addons.list.filter.' type)}}
</Button>
{{/each}}
</div>
<div
local-class='provider-list-wrapper'
>
{{#each manager.filteredAddonProviders as |provider|}}
<div
data-test-provider={{provider.name}}
local-class='provider-list-item'
>
{{provider.name}}
<Button
data-analytics-name='Connect Addon Button {{provider.name}}'
local-class='float-right'
@type='create'
{{on 'click' (fn manager.selectProvider provider)}}
>
{{t 'addons.list.connect'}}
</Button>
</div>
{{else}}
{{t 'addons.list.no-results'}}
{{/each}}
</div>
</div>
<div>
{{#each manager.filteredAddonProviders as |provider|}}
<div>
{{provider.name}}
</div>

<ul local-class='configured-addons-wrapper'>
{{#each manager.currentTypeAuthorizedAccounts as |account|}}
<li>
{{account.storageProvider.name}}
{{account.externalUserDisplayName}}
<Button
data-test-disconnect-account-button
data-analytics-name='Disconnect Addon Button {{account.storageProvider.name}}'
@type='destroy'
@disabled={{manager.disconnectAddon.isRunning}}
local-class='float-right'
{{on 'click' (perform manager.disconnectAddon account)}}
>
{{t 'addons.list.disconnect'}}
</Button>
</li>
{{else}}
{{t 'addons.list.no-results'}}
<li>{{t 'addons.list.no-authorized-accounts'}}</li>
{{/each}}
</div>
</div>
</ul>
{{/if}}
{{/if}}

<ul local-class='configured-addons-wrapper'>
{{#each manager.currentTypeAuthorizedAccounts as |account|}}
<li>
{{account.storageProvider.name}}
{{account.externalUserDisplayName}}
<Button
@type='destroy'
@disabled={{manager.disconnectAddon.isRunning}}
local-class='disconnect-button'
{{on 'click' (perform manager.disconnectAddon account)}}
>
{{t 'addons.list.disconnect'}}
</Button>
</li>
{{else}}
<li>{{t 'addons.list.no-authorized-accounts'}}</li>
{{/each}}
</ul>
</AddonsService::UserAddonsManager>
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class AddonsCardComponent extends Component<Args> {
}

get assetLogo() {
return this.args.addon.provider.links.icon;
return this.args.addon.provider.iconUrl;
}

get addonIsConfigured() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
{{#if this.otherRepoSelected}}
<Input
local-class='auth-text-input-label'
placeholder={{t 'addons.accountCreate.repo-other-placeholder'}}
@value={{this.otherRepo}}
@placeholder={{t 'addons.accountCreate.repo-other-placeholder'}}
{{on 'keyup' this.onOtherRepoChange}}
/>
{{#if this.repoOtherPostText}}
Expand All @@ -53,11 +53,11 @@
{{field.labelText}}
<Input
name={{field.name}}
placeholder={{field.inputPlaceholder}}
autocomplete={{field.autocomplete}}
@type={{field.inputType}}
@value={{field.inputValue}}
@placeholder={{field.inputPlaceholder}}
{{on 'keyup' @onInput}}
autocomplete={{field.autocomplete}}
/>
</label>
{{field.postText}}
Expand Down
Loading

0 comments on commit 96fa288

Please sign in to comment.