391 lines
19 KiB
HTML
391 lines
19 KiB
HTML
<div class="loading" ng-show="!user">
|
|
<div class="quay-spinner"></div>
|
|
</div>
|
|
|
|
<div class="loading" ng-show="user.anonymous">
|
|
No matching user found
|
|
</div>
|
|
|
|
<div class="user-admin container" ng-show="!user.anonymous">
|
|
<div class="row">
|
|
<div class="organization-header-element">
|
|
<img src="//www.gravatar.com/avatar/{{ user.gravatar }}?s=24&d=identicon">
|
|
<span class="organization-name">
|
|
{{ user.username }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Side tabs -->
|
|
<div class="col-md-2">
|
|
<ul class="nav nav-pills nav-stacked">
|
|
<!-- Billing Related -->
|
|
<li class="active" quay-require="['BILLING']"><a href="javascript:void(0)" data-toggle="tab" data-target="#plan">Plan and Usage</a></li>
|
|
<li ng-show="hasPaidPlan" quay-require="['BILLING']">
|
|
<a href="javascript:void(0)" data-toggle="tab" data-target="#billingoptions">Billing Options</a>
|
|
</li>
|
|
<li ng-show="hasPaidPlan" quay-require="['BILLING']">
|
|
<a href="javascript:void(0)" data-toggle="tab" data-target="#billing" ng-click="loadInvoices()">Billing History</a>
|
|
</li>
|
|
|
|
<!-- Non-billing -->
|
|
<li quay-classes="{'!Features.BILLING': 'active'}"><a href="javascript:void(0)" data-toggle="tab" data-target="#email">Account E-mail</a></li>
|
|
<li><a href="javascript:void(0)" data-toggle="tab" data-target="#robots">Robot Accounts</a></li>
|
|
<li><a href="javascript:void(0)" data-toggle="tab" data-target="#password">Change Password</a></li>
|
|
<li><a href="javascript:void(0)" data-toggle="tab" data-target="#external" quay-show="Features.GITHUB_LOGIN || Features.GOOGLE_LOGIN">External Logins</a></li>
|
|
<li><a href="javascript:void(0)" data-toggle="tab" data-target="#authorized" ng-click="loadAuthedApps()">Authorized Applications</a></li>
|
|
<li quay-show="Features.USER_LOG_ACCESS || hasPaidBusinessPlan">
|
|
<a href="javascript:void(0)" data-toggle="tab" data-target="#logs" ng-click="loadLogs()">Usage Logs</a>
|
|
</li>
|
|
<li quay-require="['USER_RENAME']">
|
|
<a href="javascript:void(0)" data-toggle="tab" data-target="#username">Change Username</a>
|
|
</li>
|
|
<li quay-show="Config.AUTHENTICATION_TYPE == 'Database'">
|
|
<a href="javascript:void(0)" data-toggle="tab" data-target="#migrate" id="migrateTab">Convert to Organization</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- Content -->
|
|
<div class="col-md-10">
|
|
<div class="tab-content">
|
|
<!-- Authorized applications tab -->
|
|
<div id="authorized" class="tab-pane">
|
|
<div class="quay-spinner" ng-show="!authorizedApps"></div>
|
|
|
|
<div class="panel" ng-show="authorizedApps != null">
|
|
<div class="panel-body" ng-show="!authorizedApps.length">
|
|
You have not authorized any external applications
|
|
</div>
|
|
<div class="panel-body" ng-show="authorizedApps.length">
|
|
<div class="alert alert-info">
|
|
These are the applications you have authorized to view information and perform actions on your behalf.
|
|
</div>
|
|
|
|
<table class="table">
|
|
<thead>
|
|
<th>Application Name</th>
|
|
<th>Authorized Permissions</th>
|
|
<th style="width: 150px">Revoke</th>
|
|
</thead>
|
|
|
|
<tr class="auth-info" ng-repeat="authInfo in authorizedApps">
|
|
<td>
|
|
<img src="//www.gravatar.com/avatar/{{ authInfo.gravatar }}?s=16&d=identicon">
|
|
<a href="{{ authInfo.application.url }}" ng-if="authInfo.application.url" target="_blank"
|
|
data-title="{{ authInfo.application.description || authInfo.application.name }}" bs-tooltip>
|
|
{{ authInfo.application.name }}
|
|
</a>
|
|
<span ng-if="!authInfo.application.url" data-title="{{ authInfo.application.description || authInfo.application.name }}" bs-tooltip>
|
|
{{ authInfo.application.name }}
|
|
</span>
|
|
<span class="by">{{ authInfo.application.organization.name }}</span>
|
|
</td>
|
|
<td>
|
|
<span class="label label-default scope"
|
|
ng-class="{'repo:admin': 'label-primary', 'repo:write': 'label-success', 'repo:create': 'label-success'}[scopeInfo.scope]"
|
|
ng-repeat="scopeInfo in authInfo.scopes" data-title="{{ scopeInfo.description }}" bs-tooltip>
|
|
{{ scopeInfo.scope }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="delete-ui" delete-title="'Revoke Authorization'" button-title="'Revoke'" perform-delete="deleteAccess(authInfo)"></span>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Logs tab -->
|
|
<div id="logs" class="tab-pane">
|
|
<div class="logs-view" user="user" makevisible="logsShown"></div>
|
|
</div>
|
|
|
|
<!-- Plans tab -->
|
|
<div id="plan" class="tab-pane active" quay-require="['BILLING']">
|
|
<div class="plan-manager" user="user.username" ready-for-plan="readyForPlan()" plan-changed="planChanged(plan)"></div>
|
|
</div>
|
|
|
|
<!-- E-mail address tab -->
|
|
<div id="email" class="tab-pane" quay-classes="{'!Features.BILLING': 'active'}">
|
|
<div class="row">
|
|
<div class="alert alert-success" ng-show="changeEmailSent">An e-mail has been sent to {{ sentEmail }} to verify the change.</div>
|
|
|
|
<div class="loading" ng-show="updatingUser">
|
|
<div class="quay-spinner 3x"></div>
|
|
</div>
|
|
|
|
<div class="panel" ng-show="!updatingUser">
|
|
<div class="panel-title">Account e-mail address</div>
|
|
<div class="panel-setting-content panel-body">
|
|
{{ user.email }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel" ng-show="!updatingUser" quay-show="Features.MAILING">
|
|
<div class="panel-title">Change e-mail address</div>
|
|
|
|
<div class="panel-body">
|
|
<form class="form-change col-md-6" id="changeEmailForm" name="changeEmailForm" ng-submit="changeEmail()"
|
|
ng-show="!awaitingConfirmation && !registering">
|
|
<input type="email" class="form-control" placeholder="Your new e-mail address" ng-model="cuser.email" required>
|
|
<button class="btn btn-primary" ng-disabled="changeEmailForm.$invalid || cuser.email == user.email" type="submit">Change E-mail Address</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Change password tab -->
|
|
<div id="password" class="tab-pane">
|
|
<div class="row">
|
|
<div class="panel">
|
|
<div class="panel-title">Change Password</div>
|
|
|
|
<div class="loading" ng-show="updatingUser">
|
|
<div class="quay-spinner 3x"></div>
|
|
</div>
|
|
|
|
<span class="help-block" ng-show="changePasswordSuccess">Password changed successfully</span>
|
|
|
|
<div ng-show="!updatingUser" class="panel-body">
|
|
<form class="form-change col-md-6" id="changePasswordForm" name="changePasswordForm" ng-submit="changePassword()"
|
|
ng-show="!awaitingConfirmation && !registering">
|
|
<input type="password" class="form-control" placeholder="Your new password" ng-model="cuser.password" required
|
|
ng-pattern="/^.{8,}$/">
|
|
<input type="password" class="form-control" placeholder="Verify your new password" ng-model="cuser.repeatPassword"
|
|
match="cuser.password" required ng-pattern="/^.{8,}$/">
|
|
<button class="btn btn-danger" ng-disabled="changePasswordForm.$invalid" type="submit"
|
|
analytics-on analytics-event="change_pass">Change Password</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- External Login tab -->
|
|
<div id="external" class="tab-pane" quay-show="Features.GITHUB_LOGIN || Features.GOOGLE_LOGIN">
|
|
<div class="loading" ng-show="!cuser">
|
|
<div class="quay-spinner 3x"></div>
|
|
</div>
|
|
|
|
<!-- Github -->
|
|
<div class="row" quay-show="cuser && Features.GITHUB_LOGIN">
|
|
<div class="panel">
|
|
<div class="panel-title">GitHub Login:</div>
|
|
<div class="panel-body">
|
|
<div ng-show="hasGithubLogin && githubLogin" class="lead col-md-8">
|
|
<i class="fa fa-github fa-lg" style="margin-right: 6px;" data-title="GitHub" bs-tooltip="tooltip.title"></i>
|
|
<b><a href="{{githubEndpoint}}{{githubLogin}}" target="_blank">{{githubLogin}}</a></b>
|
|
<span class="delete-ui" button-title="'Detach'" delete-title="'Detach Account'" style="margin-left: 10px"
|
|
perform-delete="detachExternalLogin('github')"></span>
|
|
</div>
|
|
<div ng-show="hasGithubLogin && !githubLogin" class="lead col-md-8">
|
|
<i class="fa fa-github fa-lg" style="margin-right: 6px;" data-title="GitHub" bs-tooltip="tooltip.title"></i>
|
|
Account attached to Github Account
|
|
<span class="delete-ui" button-title="'Detach'" delete-title="'Detach Account'" style="margin-left: 10px"
|
|
perform-delete="detachExternalLogin('github')"></span>
|
|
</div>
|
|
<div ng-show="!hasGithubLogin" class="col-md-4">
|
|
<span class="external-login-button" provider="github" action="attach"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Google -->
|
|
<div class="row" quay-show="cuser && Features.GOOGLE_LOGIN">
|
|
<div class="panel">
|
|
<div class="panel-title">Google Login:</div>
|
|
<div class="panel-body">
|
|
<div ng-show="hasGoogleLogin && googleLogin" class="lead col-md-8">
|
|
<i class="fa fa-google fa-lg" style="margin-right: 6px;" data-title="Google" bs-tooltip="tooltip.title"></i>
|
|
<b>{{ googleLogin }}</b>
|
|
<span class="delete-ui" button-title="'Detach'" delete-title="'Detach Account'" style="margin-left: 10px"
|
|
perform-delete="detachExternalLogin('google')"></span>
|
|
</div>
|
|
<div ng-show="hasGoogleLogin && !googleLogin" class="lead col-md-8">
|
|
<i class="fa fa-google fa-lg" style="margin-right: 6px;" data-title="Google" bs-tooltip="tooltip.title"></i>
|
|
Account attached to Google Account
|
|
<span class="delete-ui" button-title="'Detach'" delete-title="'Detach Account'" style="margin-left: 10px"
|
|
perform-delete="detachExternalLogin('google')"></span>
|
|
</div>
|
|
<div ng-show="!hasGoogleLogin" class="col-md-4">
|
|
<span class="external-login-button" provider="google" action="attach"></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- Robot accounts tab -->
|
|
<div id="robots" class="tab-pane">
|
|
<div class="robots-manager" user="user"></div>
|
|
</div>
|
|
|
|
<!-- Billing options tab -->
|
|
<div id="billingoptions" class="tab-pane" quay-require="['BILLING']">
|
|
<div class="billing-options" user="user"></div>
|
|
</div>
|
|
|
|
<!-- Billing History tab -->
|
|
<div id="billing" class="tab-pane" quay-require="['BILLING']">
|
|
<div class="billing-invoices" user="user" makevisible="invoicesShown"></div>
|
|
</div>
|
|
|
|
<!-- Change username tab -->
|
|
<div id="username" class="tab-pane" quay-show="Features.USER_RENAME">
|
|
<div class="row">
|
|
<div class="panel">
|
|
<div class="panel-title">Change Username</div>
|
|
|
|
<div class="loading" ng-show="updatingUser">
|
|
<div class="quay-spinner 3x"></div>
|
|
</div>
|
|
|
|
<span class="help-block" ng-show="changeUsernameSuccess">Username changed successfully</span>
|
|
|
|
<div ng-show="!updatingUser" class="panel-body">
|
|
<form class="form-change col-md-6" id="changeUsernameForm" name="changeUsernameForm" ng-submit="changePassword()"
|
|
ng-show="!awaitingConfirmation && !registering">
|
|
<input type="text" class="form-control" placeholder="Your new username" ng-model="cuser.username" required
|
|
ng-pattern="/{{ USER_PATTERN }}/">
|
|
<button class="btn btn-danger" ng-disabled="changeUsernameForm.$invalid" type="submit"
|
|
analytics-on analytics-event="change_username">Change Username</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Convert to organization tab -->
|
|
<div id="migrate" class="tab-pane" quay-show="Config.AUTHENTICATION_TYPE == 'Database'">
|
|
<!-- Step 0 -->
|
|
<div class="panel" ng-show="convertStep == 0">
|
|
<div class="panel-body" ng-show="user.organizations.length > 0">
|
|
<div class="alert alert-info">
|
|
Cannot convert this account into an organization, as it is a member of {{user.organizations.length}} other
|
|
organization{{user.organizations.length > 1 ? 's' : ''}}. Please leave
|
|
{{user.organizations.length > 1 ? 'those organizations' : 'that organization'}} first.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel-body" ng-show="user.organizations.length == 0">
|
|
<div class="alert alert-warning">
|
|
Note: Converting a user account into an organization <b>cannot be undone</b>
|
|
</div>
|
|
|
|
<button class="btn btn-primary" ng-click="showConvertForm()">Start conversion process</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 1 -->
|
|
<div class="convert-form" ng-show="convertStep == 1">
|
|
<h3>Convert to organization</h3>
|
|
|
|
<form method="post" name="convertForm" id="convertForm" ng-submit="convertToOrg()">
|
|
<div class="form-group">
|
|
<label for="orgName">Organization Name</label>
|
|
<div class="existing-data">
|
|
<img src="//www.gravatar.com/avatar/{{ user.gravatar }}?s=24&d=identicon">
|
|
{{ user.username }}</div>
|
|
<span class="description">This will continue to be the namespace for your repositories</span>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="orgName">Admin User</label>
|
|
<input id="adminUsername" name="adminUsername" type="text" class="form-control" placeholder="Admin Username"
|
|
ng-model="org.adminUser" required autofocus>
|
|
<input id="adminPassword" name="adminPassword" type="password" class="form-control" placeholder="Admin Password"
|
|
ng-model="org.adminPassword" required>
|
|
<span class="description">
|
|
The username and password for the account that will become an administrator of the organization.
|
|
Note that this account <b>must be a separate registered account</b> from the account that you are
|
|
trying to convert, and <b>must already exist</b>.
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Plans Table -->
|
|
<div class="form-group plan-group" quay-require="['BILLING']">
|
|
<label>Organization Plan</label>
|
|
<div class="plans-table" plans="orgPlans" current-plan="org.plan"></div>
|
|
</div>
|
|
|
|
<div class="button-bar">
|
|
<button class="btn btn-large btn-danger" type="submit"
|
|
ng-disabled="convertForm.$invalid || (Features.BILLING && !org.plan)"
|
|
analytics-on analytics-event="convert_to_organization">
|
|
Convert To Organization
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Modal message dialog -->
|
|
<div class="modal fade" id="cannotconvertModal">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
<h4 class="modal-title">Cannot convert account</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
Your account could not be converted. Please try again in a moment.
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div><!-- /.modal-content -->
|
|
</div><!-- /.modal-dialog -->
|
|
</div><!-- /.modal -->
|
|
|
|
|
|
<!-- Modal message dialog -->
|
|
<div class="modal fade" id="invalidadminModal">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
<h4 class="modal-title">Username or password invalid</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
The username or password specified for the admin account is not valid.
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
</div>
|
|
</div><!-- /.modal-content -->
|
|
</div><!-- /.modal-dialog -->
|
|
</div><!-- /.modal -->
|
|
|
|
|
|
<!-- Modal message dialog -->
|
|
<div class="modal fade" id="reallyconvertModal">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
<h4 class="modal-title">Convert to organization?</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="alert alert-danger">You will not be able to login to this account once converted</div>
|
|
<div>Are you <b>absolutely sure</b> you would like to convert this account to an organization? Once done, there is no going back.</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-danger" data-dismiss="modal" ng-click="reallyConvert()">Absolutely: Convert Now</button>
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
</div>
|
|
</div><!-- /.modal-content -->
|
|
</div><!-- /.modal-dialog -->
|
|
</div><!-- /.modal -->
|