initial import for Open Source 🎉

This commit is contained in:
Jimmy Zelinskie 2019-11-12 11:09:47 -05:00
parent 1898c361f3
commit 9c0dd3b722
2048 changed files with 218743 additions and 0 deletions

View file

@ -0,0 +1,62 @@
<div class="cor-container about-us">
<h2>
About Us
</h2>
<div class="row">
<div class="col-sm-12 about-basic-info">
<h3>The Basics</h3>
</div>
<div class="col-sm-3">
<div class="about-basic-icon"><i class="fa fa-3x fa-calendar"></i></div>
<div class="about-basic-text">
<b> Founded</b><br>
2012
</div>
</div>
<div class="col-sm-3">
<div class="about-basic-icon"><i class="fa fa-3x fa-globe"></i></div>
<div class="about-basic-text">
<b> Location</b><br>
New York City, NY
</div>
</div>
<div class="col-sm-3">
<div class="about-basic-icon"><img src="/static/img/coreos-globe-color-lg.png" style="height: 42px; vertical-align: bottom;"></div>
<div class="about-basic-text">
<b> CoreOS</b><br>
August, 2014
</div>
</div>
<div class="col-sm-3">
<div class="about-basic-text">
<img src="/static/img/RedHat.svg" style="height: 42px; vertical-align: bottom;"><br>
January, 2018
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<h3>Packages and Projects used</h3>
<table class="co-table co-fixed-table" style="margin-top: 20px;">
<thead>
<tr>
<td>Project Name</td>
<td>Project License</td>
<td>Type</td>
</tr>
</thead>
</table>
<div style="height: 300px; overflow-y: auto;">
<table class="co-table co-fixed-table">
<tr ng-repeat="project in billOfMaterials">
<td>{{project.project}}</td>
<td>{{project.license}}</td>
<td>{{project.format}}</td>
</tr>
</table>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,31 @@
<div class="repo-list page-content">
<div class="cor-title">
<span class="cor-title-link"></span>
<span class="cor-title-content">Applications</span>
</div>
<!-- Loading -->
<div class="cor-loader" ng-if="loading || user.beforeload"></div>
<!-- Not signed in -->
<div class="co-main-content-panel" ng-if="!loading && user.anonymous && !user.beforeload">
<!-- The user is not logged in -->
<div class="cor-container signin-container row">
<!-- Sign In -->
<div class="user-setup" redirect-url="redirectUrl"></div>
</div>
</div>
<!-- Signed in -->
<div class="row" ng-if="!loading && !user.anonymous">
<div class="col-md-12">
<div class="repo-list-panel co-main-content-panel">
<div class="repo-list-view" namespaces="namespaces" repo-kind="application"
in-read-only-mode="inReadOnlyMode">
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,19 @@
<div class="resource-view repository-view"
resource="repositoryResource"
error-message="'Application not found'">
<!-- Image repository error -->
<div class="co-main-content-panel" ng-if="viewScope.repository.kind == 'image'">
<div class="error-view-element">
<h2><span class="repo-circle no-background" repo="viewScope.repository"></span>{{ viewScope.repository.namespace }}/{{ viewScope.repository.name }}</h2>
<h3>This name refers to a <strong>container image</strong> repository</h3>
<div style="margin-bottom: 20px;">
View the <a href="/repository/{{ viewScope.repository.namespace }}/{{ viewScope.repository.name }}/">{{ viewScope.repository.namespace }}/{{ viewScope.repository.name }} image repository</a>
</div>
</div>
</div>
<!-- Application repository view -->
<div ng-if="viewScope.repository.kind == 'application'">
<app-public-view repository="viewScope.repository"></app-public-view>
</div>
</div>

View file

@ -0,0 +1,37 @@
<div class="billing-page page-content">
<div class="resource-view" resource="entityResource" error-message="'Could not load entity'">
<div class="cor-title" ng-if="organization">
<span class="cor-title-link">
<a class="back-link" href="/organization/{{ organization.name }}?tab=settings">
<span class="avatar" size="24" data="organization.avatar"></span>
{{ organization.name }}
</a>
</span>
<span class="cor-title-content">
Account Plan
</span>
</div>
<div class="cor-title" ng-if="viewuser">
<span class="cor-title-link">
<a class="back-link" href="/user/{{ viewuser.username }}?tab=settings">
<span class="avatar" size="24" data="viewuser.avatar"></span>
{{ viewuser.username }}
</a>
</span>
<span class="cor-title-content">
Account Plan
</span>
</div>
<div class="co-main-content-panel" style="min-height: 500px;">
<div ng-if="!invaliduser">
<div class="plan-manager" organization="organization.name" has-subscription="hasSubscription" ng-if="organization"></div>
<div class="plan-manager" user="viewuser" has-subscription="hasSubscription" ng-if="!organization"></div>
</div>
<div class="co-alert co-alert-danger" ng-if="invaliduser">
You do not have access to this resource
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,9 @@
<div class="build-statuses">
<div ng-repeat="build in buildsInfo">
<div class="build-status" build="build"></div>
</div>
<div ng-show="buildsInfo.length == 0">
All Dockerfile builds complete
</div>
</div>

View file

@ -0,0 +1,66 @@
<div class="build-view">
<div class="resource-view" resources="[buildResource, repoResource]"
error-message="'Build not found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/repository/{{ namespace }}/{{ name }}?tab=builds">
<i class="fa fa-hdd-o" style="margin-right: 4px"></i>
{{ namespace }}/{{ name }}
</a>
</span>
<span class="cor-title-content">
<i class="fa fa-tasks fa-lg" style="margin-right: 10px"></i> {{ build.display_name }}
</span>
</div>
<div class="co-main-content-panel">
<!-- Build Information -->
<div class="build-info-bar" build="build" show-time="false"></div>
<!-- Error Status -->
<div class="co-alert co-alert-warning" ng-show="originalBuild.error"
style="margin-bottom: 8px; margin-top: 12px;">
{{ originalBuild.error }}
</div>
<!-- Current Status -->
<div class="build-status-header" ng-show="!originalBuild.error">
<span class="build-icon-message" ng-class="build.phase">
<span class="build-state-icon" build="build"></span>
<span class="build-message" phase="build.phase"></span>
</span>
<span class="cor-options-menu">
<span class="cor-option" option-click="toggleTimestamps()">
<span ng-if="showLogTimestamps">
<i class="fa fa-clock-o"></i> Hide Timestamps
</span>
<span ng-if="!showLogTimestamps">
<i class="fa fa-clock-o"></i> Show Timestamps
</span>
</span>
<span class="cor-option" option-click="askCancelBuild(build)" ng-show="!inReadOnlyMode">
<i class="fa fa-times"></i> Cancel Build
</span>
</span>
<div class="timing">
<i class="fa fa-clock-o"></i>
Build started
<time-ago datetime="build.started"></time-ago>
</div>
</div>
<!-- Build Logs -->
<div class="build-logs-view"
build="originalBuild"
use-timestamps="showLogTimestamps"
build-updated="setUpdatedBuild(build)"
is-super-user="false"
ng-show="!originalBuild.error"></div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,18 @@
<div class="confirm-invite">
<div class="cor-container signin-container">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<div class="user-setup" ng-show="user.anonymous" redirect-url="redirectUrl"
invite-code="inviteCode">
</div>
<div class="cor-loader-inline" ng-show="!user.anonymous && loading"></div>
<div class="error-view-element" ng-show="!user.anonymous && invalid">
<h2><i class="fa fa-exclamation-triangle"></i> Confirmation Error</h2>
<h3>Confirmation code does not match this account</h3>
<div>{{ invalid }}</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,25 @@
<div class="cor-container">
<h2>
Contact Us<br>
<small>We are here to help!</small>
</h2>
<div class="row contact-options">
<div class="text-center" ng-repeat="info in Config.CONTACT_INFO"
ng-class="['option-' + getKind(info), 'col-sm-' + colsize]">
<span class="fa-stack fa-3x text-center">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-stack-1x fa-inverse"
ng-class="{'mailto': 'fa-envelope', 'irc': 'fa-comment', 'tel': 'fa-phone', 'twitter': 'fa-twitter', 'url': 'fa-ticket'}[getKind(info)]"></i>
</span>
<span ng-switch="getKind(info)">
<h4 ng-switch-when="mailto">Email</h4>
<h4 ng-switch-when="irc">IRC</h4>
<h4 ng-switch-when="tel">Call</h4>
<h4 ng-switch-when="twitter">Tweet</h4>
<h4 ng-switch-when="url">Help System</h4>
</span>
<h4><a ng-href="{{ info }}">{{ getTitle(info) }}</a></h4>
</div>
</div>
</div>

View file

@ -0,0 +1,21 @@
<div class="resource-view"
resource="repositoryResource"
error-message="'Repository not found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/repository/{{ namespace }}/{{ name }}">
{{ namespace }} / {{ name }}
</a>
</span>
<span class="cor-title-content">
<i class="fa fa-bell" style="margin-right: 10px"></i>
Create repository notification
</span>
</div>
<div class="co-main-content-panel">
<div class="create-external-notification" repository="repository" notification-created="notificationCreated()"></div>
</div>
</div>
</div>

View file

@ -0,0 +1,57 @@
<div class="error-view-element">
<div ng-switch on="info.reason">
<!-- Confirmation error -->
<div ng-switch-when="confirmerror">
<h2><i class="fa fa-exclamation-triangle"></i> Confirmation Error</h2>
<h3>{{ info.error_message || 'There was an error confirming your e-mail address' }}</h3>
<div>
If you've received this error after trying to recover your account, please perform the recovery process again.
</div>
</div>
<!-- OAuth login error -->
<div ng-switch-when="ologinerror">
<h2><i class="fa fa-exclamation-triangle"></i>{{ info.service_name }} login error</h2>
<h3 ng-if="info.error_message">{{ info.error_message }}</h3>
<div ng-if="info.user_creation && info.register_redirect">
To continue, please register using the <a href="/signin">registration form</a>.
You will be able to reassociate this {{ info.service_name }} account to your new Quay account in the user settings panel.
</div>
</div>
<!-- Otherwise -->
<div ng-switch-default>
<!-- 404 -->
<div class="err404" ng-if="code == 404">
<h2>404: Not Found</h2>
<h3 ng-if="!info.for_repo && !info.namespace_exists">The resource you're looking for doesn't exist</h3>
<h3 ng-if="info && !info.namespace_exists">Namespace <strong>{{ info.namespace }}</strong> doesn't exist</h3>
<h3 ng-if="info && info.for_repo && info.namespace_exists">The repository you're looking for doesn't exist</h3>
<img src="/static/img/40x/quay-logo-404.svg">
<h4 ng-if="!info.for_repo && !info.namespace_exists">
Return to the <a href="/">main page</a>
</h4>
<h4 ng-if="info && !info.namespace_exists && info.namespace">
<a href="/organizations/new?namespace={{ info.namespace }}">Create this namespace</a> or return to the <a href="/">main page</a>
</h4>
<h4 ng-if="info && info.for_repo && info.namespace_exists && info.namespace">
<a href="/new?namespace={{ info.namespace }}&name={{ info.repo_name }}">Create this repository</a> or return to the <a href="/">main page</a>
</h4>
</div>
<!-- 403 -->
<div class="err403" ng-if="code == 403">
<h2>403: Unauthorized</h2>
<h3 ng-if="!info.for_repo">You are not authorized to view this resource</h3>
<h3 ng-if="info.for_repo">You are not authorized to view this repository</h3>
<img src="/static/img/40x/RHQ-logomark.svg">
<h4 ng-if="info.for_repo">Contact the admin of the <strong>{{ info.namespace }}</strong> namespace for access to the repository or you can return to the <a href="/">main page</a></h4>
<h4 ng-if="!info.for_repo">Return to the <a href="/">main page</a></h4>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,10 @@
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link"></span>
<span class="cor-title-content">Experiment: New Security Scanner Layout</span>
</div>
<div class="co-main-content-panel">
<button class="btn btn-success" ng-if="!isEnabled" ng-click="setEnabled(true)">Enable Experiment</button>
<button class="btn btn-failure" ng-if="isEnabled" ng-click="setEnabled(false)">Disable Experiment</button>
</div>
</div>

View file

@ -0,0 +1,5 @@
<div class="cor-container">
<h3>Redirecting...</h3>
<META http-equiv="refresh" content="0;URL=http://docs.quay.io/solution/getting-started.html">
If this page does not redirect, please <a href="http://docs.quay.io/solution/getting-started.html"> click here</a>.
</div>

View file

@ -0,0 +1,21 @@
<div>
<div class="cor-loader" ng-show="currentStep == States.LOADING"></div>
<div class="page-content" quay-show="Features.SUPER_USERS">
<div class="cor-title">
<span class="cor-title-link"></span>
<span class="cor-title-content">Red Hat Quay Setup Incomplete</span>
</div>
<div class="co-main-content-panel" style="padding: 20px;">
<div class="co-alert co-alert-warning">
<div><strong>Your configuration is not setup yet</strong></div>
<div>Please refer to
<a target="_blank" href="https://coreos.com/quay-enterprise/docs/latest/initial-setup.html">
the docs to set up your instance.
</a>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,37 @@
<div class="billing-page page-content">
<div class="resource-view" resource="entityResource" error-message="'Could not load entity'">
<div class="cor-title" ng-if="organization">
<span class="cor-title-link">
<a class="back-link" href="/organization/{{ organization.name }}?tab=settings">
<span class="avatar" size="24" data="organization.avatar"></span>
{{ organization.name }}
</a>
</span>
<span class="cor-title-content">
Billing Invoices
</span>
</div>
<div class="cor-title" ng-if="viewuser">
<span class="cor-title-link">
<a class="back-link" href="/user/{{ viewuser.username }}?tab=settings">
<span class="avatar" size="24" data="viewuser.avatar"></span>
{{ viewuser.username }}
</a>
</span>
<span class="cor-title-content">
Billing Invoices
</span>
</div>
<div class="co-main-content-panel" style="min-height: 500px;">
<div ng-if="!invaliduser">
<div class="billing-invoices" user="viewuser" makevisible="true" ng-if="!organization"></div>
<div class="billing-invoices" organization="organization" makevisible="true" ng-if="organization"></div>
</div>
<div class="co-alert co-alert-danger" ng-if="invaliduser">
You do not have access to this resource
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,7 @@
<div class="cor-container signin-container">
<div class="row">
<div class="col-sm-4 col-sm-offset-4">
<div class="user-setup" redirect-url="redirectUrl"></div>
</div>
</div>
</div>

View file

@ -0,0 +1,4 @@
<div quay-static-include="{'hosted': 'index.html', 'otherwise': 'partials/landing-login.html'}"
onload="chromify()">
<span class="cor-loader"></span>
</div>

View file

@ -0,0 +1,186 @@
<div class="resource-view manage-application"
resource="appResource"
error-message="'Application not found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/organization/{{ organization.name }}?tab=applications">
<span class="avatar" size="24" data="organization.avatar"></span>
{{ organization.name }}
</a>
</span>
<span class="cor-title-content">
{{ application.name }}
</span>
</div>
<div class="row" style="padding: 14px; padding-top: 0px; padding-bottom: 0px;" ng-if="!application.redirect_uri">
<div class="co-alert co-alert-warning">
Warning: There is no OAuth Redirect setup for this application. Please enter it in the <strong>Settings</strong> tab.
</div>
</div>
<cor-tab-panel orientation="vertical" cor-nav-tabs>
<cor-tabs>
<cor-tab tab-title="Settings" tab-id="settings">
<i class="fa fa-gear"></i>
</cor-tab>
<cor-tab tab-title="OAuth Information" tab-id="oauth">
<i class="fa fa-key"></i>
</cor-tab>
<cor-tab tab-title="Delete Application" tab-id="delete">
<i class="fa fa-times"></i>
</cor-tab>
<cor-tab tab-title="Generate Token" tab-id="gen-token">
<i class="fa fa-ticket"></i>
</cor-tab>
</cor-tabs>
<cor-tab-content>
<!-- Settings tab -->
<cor-tab-pane id="settings">
<form method="put" name="applicationForm" id="applicationForm" ng-submit="updateApplication()">
<div class="form-group nested">
<label for="fieldAppName">Application Name</label>
<input type="text" class="form-control" id="fieldAppName" placeholder="Application Name" required ng-model="application.name">
<div class="description">The name of the application that is displayed to users</div>
</div>
<div class="form-group nested">
<label for="fieldAppURI">Homepage URL</label>
<input type="url" class="form-control" id="fieldAppURI" placeholder="Homepage URL" required ng-model="application.application_uri">
<div class="description">The URL to which the application will link in the authorization view</div>
</div>
<div class="form-group nested">
<label for="fieldAppDescription">Description (optional)</label>
<input type="text" class="form-control" id="fieldAppURI" placeholder="Description" ng-model="application.description">
<div class="description">The user friendly description of the application</div>
</div>
<div class="form-group nested">
<label for="fieldAppAvatar">Avatar E-mail (optional)</label>
<input type="email" class="form-control" id="fieldAppAvatar" placeholder="Avatar E-mail" ng-model="application.avatar_email">
<div class="description">An e-mail address representing the <a href="http://docs.quay.io/glossary/avatar" ng-safenewtab>Avatar</a> for the application. See above for the icon.</div>
</div>
<div class="form-group nested" style="margin-top: 10px; padding-top: 10px; border-top: 1px solid #eee;">
<label for="fieldAppRedirect">Redirect/Callback URL Prefix</label>
<input type="url" class="form-control" id="fieldAppRedirect" placeholder="OAuth Redirect URL" ng-model="application.redirect_uri" required>
<div class="description">Allowed prefix for the application's OAuth redirection/callback URLs</div>
</div>
<div class="button-bar">
<button class="btn btn-success btn-large" type="submit" ng-disabled="applicationForm.$invalid || updating">
Update Application
</button>
<span class="quay-spinner" ng-show="updating"></span>
</div>
</form>
</cor-tab-pane>
<!-- Delete tab -->
<cor-tab-pane id="delete">
<div class="panel panel-default">
<div class="panel-body">
<div style="text-align: center">
<div class="co-alert co-alert-danger">Deleting an application <b>cannot be undone</b>. Any existing users of your application will <strong>break!</strong>. Here be dragons!</div>
<button class="btn btn-danger" ng-click="askDelete()">Delete Application</button>
</div>
</div>
</div>
</cor-tab-pane>
<!-- Generate Token tab -->
<cor-tab-pane id="gen-token">
<div class="co-alert co-alert-info">
<div style="margin-bottom: 10px">
Click the button below to generate a new <a href="http://tools.ietf.org/html/rfc6749#section-1.4" target="_new">OAuth 2 Access Token</a>.
</div>
<div>
The generated token will act on behalf of user
<span class="avatar" data="user.avatar" size="16" style="margin-left: 6px; margin-right: 4px;"></span>
<span class="user-name">{{ user.username }}</span>
</div>
</div>
<table>
<tr ng-repeat="(scopeName, scopeInfo) in OAuthService.SCOPES">
<td>
<label onclick="event.stopPropagation()">
<input type="checkbox" value="scopeInfo.scope" ng-model="genScopes[scopeName]">{{ scopeInfo.title }}
</label>
<div class="scope-description">{{ scopeInfo.description }}</div>
</td>
</tr>
</table>
<a class="btn btn-success"
href="{{ Config.getUrl('/oauth/authorize?response_type=token&client_id=' + application.client_id + '&scope=' + getScopes(genScopes).join(' ') + '&redirect_uri=' + Config.getUrl(Config['LOCAL_OAUTH_HANDLER'])) }}"
ng-disabled="!getScopes(genScopes).length" ng-safenewtab>
Generate Access Token
</a>
</cor-tab-pane>
<!-- OAuth tab -->
<cor-tab-pane id="oauth">
<dl class="dl-horizontal">
<dt>Client ID:</dt>
<dd><div class="copy-box" value="application.client_id"></div></dd>
</dl>
<dl class="dl-horizontal" style="margin-top: 20px;">
<dt>Client Secret:</dt>
<dd>{{ application.client_secret }}</dd>
</dl>
<button class="btn btn-primary" ng-click="askResetClientSecret()">Reset Client Secret</button>
</cor-tab-pane>
</cor-tab-content>
</cor-tab-panel>
</div>
</div>
<!-- Modal message dialog -->
<div class="modal fade" id="resetSecretModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Reset Client Secret?</h4>
</div>
<div class="modal-body">
<div class="alert alert-info">
Note that resetting the Client Secret for this application will <strong>not</strong> invalidate any user tokens.
</div>
<div>Are you sure you want to reset your Client Secret? Any existing users of this Secret <strong>will break!</strong></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="resetClientSecret()">Yes, I'm sure</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal message dialog -->
<div class="modal fade" id="deleteAppModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Delete Application?</h4>
</div>
<div class="modal-body">
Are you <b>absolutely, positively</b> sure you would like to delete this application? This <b>cannot be undone</b>.
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" ng-click="deleteApplication()">Delete Application</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->

View file

@ -0,0 +1,74 @@
<div class="resource-view manifest-view"
resources="[repositoryResource, manifestResource]"
error-message="'Manifest not found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/repository/{{ repository.namespace }}/{{ repository.name }}?tab=tags">
<i class="fa fa-hdd-o" style="margin-right: 4px"></i>
{{ repository.namespace }}/{{ repository.name }}
</a>
</span>
<span class="cor-title-content">
<i class="fa fa-lg" ng-class="{'fa-file': !manifest.is_manifest_list, 'fa-file-text-o': manifest.is_manifest_list}" style="margin-right: 10px"></i>
{{ manifest.digest.substr(7, 12) }}
</span>
</div>
<!-- Manifest list -->
<div ng-if="manifest.is_manifest_list">
<div class="co-main-content-panel">
<cor-table table-data="manifestsOf(manifest)" table-item-title="manifests" filter-fields="['digest', 'os', 'architecture']">
<cor-table-col datafield="digest" sortfield="digest" title="Manifest"
templateurl="/static/directives/manifest-view-manifest-link.html"></cor-table-col>
<cor-table-col datafield="os" sortfield="os" title="Operating System"></cor-table-col>
<cor-table-col datafield="architecture" sortfield="architecture" title="Architecture"></cor-table-col>
</cor-table>
</div>
</div>
<!-- Manifest -->
<div ng-if="!manifest.is_manifest_list">
<cor-tab-panel orientation="vertical" cor-nav-tabs>
<cor-tabs>
<cor-tab tab-title="Layers" tab-id="layers">
<i class="fa ci-layers"></i>
</cor-tab>
<cor-tab tab-title="Security Scan" tab-id="vulnerabilities"
tab-init="loadManifestSecurity()"
quay-show="Features.SECURITY_SCANNER">
<i class="fa fa-bug"></i>
</cor-tab>
<cor-tab tab-title="Packages" tab-id="packages"
tab-init="loadManifestPackages()"
quay-show="Features.SECURITY_SCANNER">
<i class="fa ci-package"></i>
</cor-tab>
</cor-tabs>
<cor-tab-content>
<!-- Layers -->
<cor-tab-pane id="layers">
<h3>Manifest Layers</h3>
<div class="manifest-view-layer" repository="repository" layer="layer"
manifest="manifest" ng-repeat="layer in reversedLayers"></div>
</cor-tab-pane>
<!-- Vulnerabilities -->
<cor-tab-pane id="vulnerabilities" quay-show="Features.SECURITY_SCANNER">
<div quay-require="['SECURITY_SCANNER']">
<div class="manifest-vulnerability-view" repository="repository" manifest="manifest" is-enabled="manifestSecurityCounter"></div>
</div>
</cor-tab-pane>
<!-- Features -->
<cor-tab-pane id="packages" quay-show="Features.SECURITY_SCANNER">
<div quay-require="['SECURITY_SCANNER']">
<div class="manifest-feature-view" repository="repository" manifest="manifest" is-enabled="manifestPackageCounter"></div>
</div>
</cor-tab-pane>
</cor-tab-content>
</cor-tab-panel>
</div>
</div>
</div>

View file

@ -0,0 +1,99 @@
<div class="new-organization">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/repository">
Repositories
</a>
</span>
<span class="cor-title-content">
Create New Organization
</span>
</div>
<div class="co-main-content-panel">
<div class="cor-loader" ng-show="creating"></div>
<div class="create-org" ng-show="!creating">
<!-- Step 1 -->
<div ng-show="!user || user.anonymous">
<div class="page-description">
In order to create a new organization, <b>you must first be signed in</b> as the
user that <b>will become an admin</b> for the organization.
</div>
<div class="step-container row">
<div class="col-sm-offset-3 col-sm-6">
<div class="user-setup" redirect-url="'/organizations/new'"
sign-in-started="signinStarted()"
signed-in="signedIn()"></div>
</div>
</div>
</div>
<!-- Step 2 -->
<div ng-show="user && !user.anonymous && !created">
<div class="step-container">
<div class="co-alert co-alert-danger" ng-if="createError">
{{ createError }}
</div>
<form method="post" name="newOrgForm" id="newOrgForm" ng-submit="createNewOrg()">
<div class="form-group nested">
<label for="orgName">Organization Name</label>
<div class="field-row">
<span class="field-container">
<span class="namespace-input" binding="org.name" back-incompat-message="backIncompatMessage" namespace-title="Organization name"></span>
</span>
<span class="co-alert co-alert-warning thin" ng-show="backIncompatMessage">{{ backIncompatMessage }}</span>
<span class="co-alert co-alert-danger thin" ng-show="!newOrgForm.namespaceField.$error.required && newOrgForm.namespaceField.$invalid">
Organization names must be alphanumeric, be at least 2 characters in length and max 255 characters in length
</span>
</div>
<span class="description">This will also be the namespace for your repositories. Must be alphanumeric, all lowercase, at least 2 characters long and at most 255 characters long.</span>
</div>
<div class="form-group nested" quay-require="['MAILING']">
<label for="orgName">Organization Email</label>
<div class="field-row">
<span class="field-container">
<input id="orgEmail" name="orgEmail" type="email" class="form-control" placeholder="Organization Email"
ng-model="org.email" required>
<span class="description">This address must be different from your account's email.</span>
</span>
</div>
</div>
<!-- Plans Table -->
<div class="form-group nested plan-group" quay-require="['BILLING']">
<strong>Choose your organization's plan</strong>
<div class="plans-table" plans="plans" current-plan="holder.currentPlan"></div>
</div>
<div quay-require="['RECAPTCHA']" style="margin-bottom: 10px;">
<div class="captcha">
<div vc-recaptcha ng-model="org.recaptcha_response" key="Config.RECAPTCHA_SITE_KEY"></div>
</div>
</div>
<div class="button-bar">
<button class="btn btn-large btn-primary" type="submit"
ng-disabled="newOrgForm.$invalid || (Features.BILLING && !holder.currentPlan) || (Features.RECAPTCHA && !org.recaptcha_response)"
analytics-on analytics-event="create_organization">
Create Organization
</button>
</div>
</form>
</div>
</div>
<!-- Step 3 -->
<div ng-show="user && !user.anonymous && created">
<div class="step-container">
<h3>Organization Created</h3>
<h4><a href="/organization/{{ org.name }}">Manage Teams Now</a></h4>
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,249 @@
<div class="new-repo">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/repository">
Repositories
</a>
</span>
<span class="cor-title-content">
Create New Repository
</span>
</div>
<div class="co-main-content-panel">
<div class="" ng-show="user.anonymous">
<div class="col-sm-6 col-sm-offset-3">
<div class="user-setup" redirect-url="'/new/'"></div>
</div>
</div>
<div class="cor-loader" ng-show="!user.anonymous && building"></div>
<div class="cor-loader" ng-show="!user.anonymous && creating"></div>
<div class="new-repo" ng-show="!user.anonymous && !creating && !building">
<form method="post" name="newRepoForm" id="newRepoForm" ng-submit="createNewRepo()">
<!-- Header -->
<div class="row">
<div class="col-md-12">
<div class="section">
<div class="new-header">
<div class="namespace-selector-header">
<span quay-show="Features.APP_REGISTRY">
<span class="visible-xs xs-label">Repository Kind:</span>
<select class="form-control repo-kind-select" ng-model="repo.repo_kind">
<option value="image">Container Image Repository</option>
<option value="application">Application Repository</option>
</select>
</span>
<span class="visible-xs xs-label">Namespace:</span>
<span class="namespace-selector" user="user" namespace="repo.namespace" require-create="true"></span>
<span class="slash hidden-xs">/</span>
<span class="visible-xs xs-label">Repository Name:</span>
<span class="name-container">
<input id="repoName" name="repoName" type="text" class="form-control" placeholder="Repository Name" ng-model="repo.name"
required autofocus data-trigger="manual" data-content="{{ createError }}" data-placement="right" ng-pattern="/^[.a-z0-9_-]+$/">
</span>
<span class="co-alert co-alert-warning co-alert-popin-warning" ng-show="!creating && !newRepoForm.repoName.$error.required && !newRepoForm.repoName.$valid">
Repository names must match [a-z0-9_-]+
</span>
<span class="co-alert co-alert-danger co-alert-popin-warning" ng-show="!creating && createError">
{{ createError }}
</span>
</div>
</div>
</div>
<div class="section">
<div class="section-title">Repository Description</div>
<br>
<div class="description">
<markdown-input content="repo.description"
can-write="true"
(content-changed)="updateDescription($event.content)"
field-title="repository description"></markdown-input>
</div>
</div>
</div>
</div>
<!-- Private/public -->
<div class="row">
<div class="col-md-12">
<div class="section">
<div class="section-title">Repository Visibility</div>
<br>
<div class="repo-option">
<div class="repo-option-title">
<input type="radio" id="publicrepo" name="publicorprivate" ng-model="repo.is_public" value="1">
<i class="fa fa-unlock fa-large" data-title="Public Repository"></i>
<label for="publicrepo"><strong>Public</strong></label>
</div>
<div class="option-description">
<span class="description-text">Anyone can see and pull from this repository. You choose who can push.</span>
</div>
</div>
<div class="repo-option">
<div class="repo-option-title">
<input type="radio" id="privaterepo" name="publicorprivate" ng-model="repo.is_public" value="0">
<i class="fa fa-lock fa-large" data-title="Private Repository"></i>
<label for="privaterepo"><strong>Private</strong></label>
</div>
<div class="option-description">
<span class="description-text">You choose who can see, pull and push from/to this repository.</span>
</div>
</div>
<!-- Payment -->
<div class="repo-count-checker" namespace="repo.namespace" plan-required="planRequired"
is-enabled="repo.is_public == '0'">
</div>
</div>
</div>
<div ng-show="repo.is_public == '1' || (!planRequired && !checkingPlan)">
<div class="row" ng-show="Features.BUILD_SUPPORT && repo.repo_kind == 'image'">
<div class="col-md-12">
<div class="section">
<div class="section-title">Initialize repository</div>
<div style="padding-top: 10px;">
<!-- Empty -->
<div class="repo-option">
<input type="radio" id="initEmpty" name="initialize" ng-model="repo.initialize" value="">
<i class="fa fa-hdd-o fa-lg" style="padding: 6px; padding-left: 8px; padding-right: 6px;"></i>
<label for="initEmpty" style="color: #aaa;">(Empty repository)</label>
</div>
<!-- Dockerfile -->
<div class="repo-option">
<input type="radio" id="initDockerfile" name="initialize" ng-model="repo.initialize" value="dockerfile">
<i class="fa fa-file fa-lg" style="padding: 6px; padding-left: 10px; padding-right: 8px;"></i>
<label for="initDockerfile">Initialize from a <b>Dockerfile</b></label>
</div>
<!-- SCM -->
<div class="repo-option"
ng-repeat="type in TriggerService.getTypes()"
ng-if="TriggerService.isEnabled(type)">
<input type="radio" id="init{{type}}" name="initialize" ng-model="repo.initialize" value="{{ type }}">
<i class="fa fa-lg" ng-class="TriggerService.getIcon(type)"
style="padding: 6px; padding-left: 10px; padding-right: 12px;"></i>
<label for="init{{type}}">Link to a {{ TriggerService.getTitle(type) }}</label>
</div>
</div>
</div>
</div>
</div>
<div class="row" ng-show="(repo.initialize == 'dockerfile' || repo.initialize == 'zipfile') && repo.repo_kind == 'image'">
<div class="col-md-12">
<div class="section">
<div class="section-title">Initialize from Dockerfile</div>
<div style="padding-top: 20px;">
<div class="initialize-repo">
<div class="dockerfile-build-form" repository="repo || createdForBuild"
is-ready="hasDockerfile"
ready-for-build="readyForBuild(startBuild)"></div>
</div>
</div>
</div>
</div>
</div>
<div class="row"
ng-repeat="type in TriggerService.getTypes()"
ng-if="TriggerService.isEnabled(type) && repo.initialize == type && repo.repo_kind == 'image'">
<div class="col-md-12">
<div class="co-alert co-alert-info">
You will be redirected to authorize for {{ TriggerService.getTitle(type) }} once the repository has been created
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<button class="btn btn-large btn-primary" type="submit"
ng-disabled="buildStarted || newRepoForm.$invalid || (repo.is_public == '0' && (planRequired || checkingPlan)) || ((repo.initialize == 'dockerfile' || repo.initialize == 'zipfile') && !hasDockerfile)">
<i class="fa fa-large" ng-class="repo.is_public == '1' ? 'fa-unlock' : 'fa-lock'"
style="margin-right: 4px"></i>
Create {{ repo.is_public == '1' ? 'Public' : 'Private' }} Repository
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Modal edit for the description -->
<div class="modal fade" id="editModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Edit Repository Description</h4>
</div>
<div class="modal-body">
<div class="wmd-panel">
<div id="wmd-button-bar-description"></div>
<textarea class="wmd-input" id="wmd-input-description" placeholder="Enter description">{{ repo.description }}</textarea>
</div>
<div id="wmd-preview-description" class="wmd-panel wmd-preview"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" ng-click="saveDescription()">Save changes</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal message dialog -->
<div class="modal fade" id="cannotcreateModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Cannot create repository</h4>
</div>
<div class="modal-body">
The repository could not be created.
</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="couldnotsubscribeModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Cannot upgrade plan</h4>
</div>
<div class="modal-body">
Your current plan could not be upgraded. Please try again.
</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 -->

View file

@ -0,0 +1,154 @@
<div class="resource-view org-view"
resource="orgResource"
error-message="'Organization not found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link"></span>
<span class="cor-title-content">
<span class="avatar" size="32" data="organization.avatar"></span>
<span class="organization-name">{{ organization.name }}</span>
</span>
<span class="cor-title-action" ng-if="isMember && !inReadOnlyMode">
<a href="/new/?namespace={{ organization.name }}">
<i class="fa fa-plus" data-title="Create new repository"></i>
Create New Repository
</a>
</span>
</div>
<div class="co-main-content-panel" ng-if="user.anonymous || !isMember">
<div class="repo-list-view padded" namespaces="[organization]"
in-read-only-mode="inReadOnlyMode">&nbsp;</div>
</div>
<cor-tab-panel ng-if="!user.anonymous && isMember"
orientation="vertical"
cor-nav-tabs>
<cor-tabs quay-show="isMember">
<cor-tab tab-active="true" tab-title="Repositories" tab-id="repos">
<i class="fa fa-hdd-o"></i>
</cor-tab>
<cor-tab tab-title="Teams and Membership" tab-id="teams" tab-init="showTeams()">
<i class="fa fa-users"></i>
</cor-tab>
<cor-tab tab-title="Robot Accounts" tab-id="robots" tab-init="showRobots()"
ng-show="isAdmin">
<i class="fa ci-robot"></i>
</cor-tab>
<cor-tab tab-title="Default Permissions" tab-id="default" ng-show="isAdmin">
<i class="fa ci-stamp"></i>
</cor-tab>
<cor-tab tab-title="Usage Logs" tab-id="logs"
tab-init="showLogs()" ng-show="isAdmin">
<i class="fa fa-bar-chart"></i>
</cor-tab>
<cor-tab tab-title="Applications" tab-id="applications"
tab-init="showApplications()" ng-show="isAdmin && !inReadOnlyMode">
<i class="fa ci-application"></i>
</cor-tab>
<cor-tab tab-title="Organization Settings" tab-id="settings"
ng-show="isAdmin && !inReadOnlyMode" tab-init="showBilling()">
<i class="fa fa-gears"></i>
</cor-tab>
</cor-tabs> <!-- /cor-tabs -->
<cor-tab-content>
<!-- Repositories -->
<cor-tab-pane id="repos">
<div class="repo-list-view" namespaces="[organization]"
in-read-only-mode="inReadOnlyMode"><h3>Repositories</h3></div>
</cor-tab-pane>
<!-- Teams -->
<cor-tab-pane id="teams">
<div ng-if="!user.anonymous">
<div class="teams-manager" organization="organization" is-enabled="showTeamsCounter"></div>
</div>
</cor-tab-pane>
<!-- Robot Accounts -->
<cor-tab-pane id="robots">
<div ng-if="isAdmin">
<div class="robots-manager" organization="organization" is-enabled="showRobotsCounter"></div>
</div>
</cor-tab-pane>
<!-- Default Permissions -->
<cor-tab-pane id="default">
<div ng-if="isAdmin">
<div class="prototype-manager" organization="organization"></div>
</div>
</cor-tab-pane>
<!-- Usage Logs -->
<cor-tab-pane id="logs">
<div class="logs-view" organization="organization" makevisible="showLogsCounter"></div>
</cor-tab-pane>
<!-- Applications -->
<cor-tab-pane id="applications">
<div class="application-manager" organization="organization"
makevisible="showApplicationsCounter"></div>
</cor-tab-pane>
<!-- Settings -->
<cor-tab-pane id="settings">
<div ng-if="isAdmin">
<!-- Org Settings -->
<div class="settings-section">
<h3>Organization Settings</h3>
<table class="co-list-table">
<tr>
<td>Namespace:</td>
<td>
{{ organization.name }}
<div class="help-text">Organization names cannot currently be changed. Please <a href="/contact">contact support</a> to migrate accounts.</div>
</td>
</tr>
<tr>
<td>Avatar:</td>
<td>
<span class="avatar" size="48" data="organization.avatar"></span>
<div class="help-text" ng-if="Config.AVATAR_KIND == 'local'">Avatar is generated based off the organization's name.</div>
<div class="help-text" ng-if="Config.AVATAR_KIND == 'gravatar' && Features.MAILING">Avatar is served by <a href="http://gravatar.com" rel="nofollow" target="_blank">Gravatar</a> based on the {{ organization.email }} e-mail address.</div>
<div class="help-text" ng-if="Config.AVATAR_KIND == 'gravatar' && !Features.MAILING">Avatar is served by <a href="http://gravatar.com" rel="nofollow" target="_blank">Gravatar</a> based on the unique ID: {{ organization.email }}.</div>
</td>
</tr>
<tr quay-show="Features.MAILING">
<td>Email Address:</td>
<td>
<a class="co-modify-link" ng-click="showChangeEmail()">{{ organization.email }}</a>
</td>
</tr>
</table>
<div class="delete-namespace-view" subscription-status="subscriptionStatus" organization="organization" namespace-title="organization"></div>
<time-machine-settings organization="organization"></time-machine-settings>
</div>
<!-- Billing Information -->
<div class="settings-section" quay-show="Features.BILLING">
<h3>Billing Information</h3>
<div class="billing-management-panel" organization="organization" is-enabled="showBillingCounter" subscription-status="subscriptionStatus"></div>
</div>
</div>
</cor-tab-pane>
</cor-tab-content>
</cor-tab-panel>
</div>
<!-- Change email dialog -->
<div class="cor-confirm-dialog"
dialog-context="changeEmailInfo"
dialog-action="changeEmail(info, callback)"
dialog-title="Change E-mail Address"
dialog-action-title="Change Email"
dialog-form="context.emailform">
<form name="context.emailform" class="co-single-field-dialog">
Please enter a new email address.
<input type="email" class="form-control" placeholder="Your new e-mail address"
ng-model="changeEmailInfo.email" required>
</form>
</div>
</div>

View file

@ -0,0 +1,33 @@
<div class="cor-container org-list conntent-container">
<div class="loading" ng-show="!user">
<div class="quay-spinner"></div>
</div>
<div class="button-bar-right">
<a href="/organizations/new/" data-title="Starts the process to create a new organization" bs-tooltip="tooltip.title">
<button class="btn btn-success">
<i class="fa fa-plus"></i>
Create New Organization
</button>
</a>
<a href="/user/?tab=migrate" data-title="Starts the process to convert this account into an organization" bs-tooltip="tooltip.title" quay-show="Config.AUTHENTICATION_TYPE == 'Database' && !user.anonymous">
<button class="btn btn-primary">
<i class="fa fa-caret-square-o-right"></i>
Convert account
</button>
</a>
</div>
<!-- Organizations -->
<div ng-if="user.organizations.length > 0">
<h2>Organizations</h2>
<div class="organization-listing" ng-repeat="organization in user.organizations">
<span class="avatar" size="32" data="organization.avatar"></span>
<a class="org-title" href="/organization/{{ organization.name }}">{{ organization.name }}</a>
</div>
</div>
<!-- Organization Help/Tour -->
<div class="tour-content" ng-if="!user.organizations || user.organizations.length == 0" kind="'organizations'"></div>
</div>

View file

@ -0,0 +1,3 @@
<div class="co-main-content-panel plans-panel">
<div class="plans-display"></div>
</div>

View file

@ -0,0 +1,83 @@
<div class="container privacy-policy">
<h2>CoreOS Privacy Policy</h2>
<h4>Last Revised: February 2, 2015</h4>
<p>Welcome to Quay from CoreOS, Inc. (“<strong>CoreOS</strong>”, “<strong>we</strong>”, “<strong>us</strong>” or “<strong>our</strong>”).</p>
<p>This privacy policy explains how we collect, use and disclose information about you when you use any of the websites owned or operated by CoreOS (the “<strong>Sites</strong>”) and any of the online products and services that link to this privacy policy (collectively, the “<strong>Services</strong>”) or when you otherwise interact with us. By using any of our Services, you consent to our collection, use and disclosure of your information as described in this privacy policy.</p>
<p>The Services allow users to store, manage, and retrieve container repositories.</p>
<p>We may change this privacy policy from time-to-time. If we make changes, we will notify you by revising the date at the top of the policy and, in some cases, we will provide you with additional notice (such as adding a statement to our homepage or sending you an email notification). We encourage you to review the privacy policy periodically to stay informed about our practices and the ways you can help protect your privacy.</p>
<dl>
<dt class="section">Collection of Information</dt>
<dt>Information You Provide to Us</dt>
<dd>
We collect information you directly give us. For example, we collect information about you when you sign up for one of our Services, participate in any interactive features of the Services, fill out a form, give feedback, ideas or submissions about any of the Services, communicate with us via third party social media sites, request customer support or otherwise communicate with us. The types of information we may collect include your email address, username, your credit/debit card information and any other information you choose to provide. For information as to how to restrict the collection of contact information, please see the “<a href="#your-choices">Your Choices</a>” section below. If you choose not to provide certain information, we may not be able to provide certain of our Services to you or certain features of our Services may be unavailable or work differently.
</dd>
<dt>Information We Collect Automatically When You Use the Services</dt>
<dd>
When you access or use our Services (or certain portions of the Services), we automatically collect certain information about you. This information includes:
<ul>
<li><strong>Log Information:</strong> We log information about your use of the Services, including the type of device you use, access times, IP address, pages viewed, and the page you visited before navigating to one of our Services. We use this information for analytic and product improvement purposes.</li>
<li><strong>Device Information:</strong> We collect information about the computer you use to access our Services, including the hardware model, operating system and version and unique device identifiers.</li>
<li><strong>Information Collected by Cookies and Other Tracking Technologies:</strong> We use various technologies to collect information, and this may include cookies and web beacons. Cookies are small data files stored on your hard drive or in device memory. Web beacons (also known as “tracking pixels”) are non-visible electronic images. These technologies are used for analytic and product improvement purposes, such as seeing which areas and features of our Services are popular and determining whether an email has been opened and acted upon. For more information about cookies, and how to disable them, please see “<a href="#your-choices">Your Choices</a>” below.</li>
</ul>
</dd>
<dt>Information We Collect From Other Sources</dt>
<dd>
We may also obtain information from other sources and combine that with information we collect through our Services. For example, if you create or log into your account through a site like Google.com or GitHub.com, we will have access to certain information from that site, such as your name, account information and friends lists, in accordance with the authorization procedures determined by these sites.
</dd>
<dt class="section">Use of Information</dt>
<dd>We may use information about you for various purposes, including to:
<ul>
<li>Provide, deliver, maintain, test and improve our Services;</li>
<li>Send you technical notices, updates, confirmations, security alerts and support and administrative messages;</li>
<li>Respond to your comments, questions and requests and provide customer service;</li>
<li>Communicate with you about products, services, offers, promotions, rewards and events offered by CoreOS and others, and provide news and information we think will be of interest to you;</li>
<li>Monitor and analyze trends, usage and activities in connection with our Services and improve our Services;</li>
<li>Detect, investigate and prevent any suspected breaches of the terms applicable to the use of our Services (including, our Sites); and</li>
<li>Link or combine with information we get from others to help understand your needs and provide you with better service.</li>
</ul>
CoreOS is based in the United States, and the information we collect is governed by U.S. law. By accessing or using any of our Services or otherwise providing information to us, you consent to the processing and transfer of information in and to the U.S. and other countries.
</dd>
<dt class="section">Sharing of Information</dt>
<dd>
We may share information about you as follows or as otherwise described in this Privacy Policy:
<ul>
<li>With vendors, consultants and other service providers who need access to such information to carry out work on our behalf;</li>
<li>In response to a request for information if we believe disclosure is in accordance with any applicable law, regulation or legal process, or as otherwise required by any applicable law, rule or regulation;</li>
<li>If we believe your actions are inconsistent with the spirit or language of our user agreements or policies, or to protect the rights, property and safety of CoreOS or others;</li>
<li>In connection with, or during negotiations of, any financing with respect to CoreOS;</li>
<li>In connection with, or during negotiations of, any merger, sale of CoreOS assets or acquisition of all or a portion of our business to another company; and</li>
<li>With your consent or at your direction, including if we notify you through any of the Services that the information you provide will be shared in a particular manner and you provide such information.</li>
</ul>
We may also share aggregated or anonymized information that does not directly identify you.
</dd>
<dt class="section">Security</dt>
<dd>
We take reasonable measures to help protect information about you from loss, theft, misuse and unauthorized access, disclosure, alteration and destruction.
</dd>
<dt class="section">Analytics Services</dt>
<dd>
We may allow others to provide analytics services in connection with the Services (or portions the Services). These entities may use cookies, web beacons and other technologies to collect information about your use of the Services and other websites, including your IP address, web browser, pages viewed, time spent on pages, links clicked and conversion information. We and others may use this information to, among other things, analyze and track data, determine the popularity of certain content, personalize the user experience, and better understand your activity.
</dd>
<dt class="section"><a id="your-choices"></a>Your Choices</dt>
<dt>Account Information</dt>
<dd>
If you wish to delete your account, please contact support at <a href="mailto:support@quay.io">support@quay.io</a>. Note that we may retain certain information as required by law or for legitimate business purposes as may be necessary to fulfill the purposes identified in the privacy policy. We may also retain cached or archived copies of information (including, location information) about you for a certain period of time.
</dd>
<dt>Cookies</dt>
<dd>
Most web browsers are set to accept cookies by default. If you prefer, you can usually choose to set your browser to remove or reject browser cookies. Please note that if you choose to remove or reject cookies, this could affect the availability and functionality of certain of the Services.
</dd>
<dt>Promotional Communications</dt>
<dd>
You may opt out of receiving promotional communications from CoreOS by following the instructions in those communications. If you opt out, we may still send you non-promotional communications, such as those about your account or our ongoing business relations.
</dd>
<dt>Contact Us</dt>
<dd>
If you have any questions or concerns about this privacy policy or any privacy issues, please email us at <a href="mailto:partners@coreos.com">partners@coreos.com</a>.
</dd>
</dl>
</div>

View file

@ -0,0 +1,62 @@
<div class="repo-list page-content">
<div class="cor-title">
<span class="cor-title-link"></span>
<span class="cor-title-content">Repositories</span>
<span class="cor-title-action" ng-if="!user.anonymous && !inReadOnlyMode">
<a href="/new/">
<i class="fa fa-plus" data-title="Create new repository"></i>
Create New Repository
</a>
</span>
</div>
<!-- Loading -->
<div class="cor-loader" ng-if="loading || user.beforeload"></div>
<!-- Not signed in -->
<div class="co-main-content-panel" ng-if="!loading && user.anonymous && !user.beforeload">
<!-- The user is not logged in -->
<div class="cor-container signin-container row">
<!-- Sign In -->
<div class="user-setup" redirect-url="redirectUrl"></div>
</div>
</div>
<!-- Signed in -->
<div class="row" ng-if="!loading && !user.anonymous">
<div class="col-lg-3 col-lg-push-9 col-md-3 col-md-push-9 col-sm-12">
<div class="co-main-content-panel repo-list-namespaces">
<h4>Users and Organizations</h4>
<ul class="namespaces-list">
<li ng-repeat="namespace in namespaces">
<a href="/user/{{ namespace.name }}" ng-if="!isOrganization(namespace.name)">
<span class="avatar" size="30" data="namespace.avatar"></span>
{{ namespace.name }}
</a>
<a href="/organization/{{ namespace.name }}" ng-if="isOrganization(namespace.name)">
<span class="avatar" size="30" data="namespace.avatar"></span>
{{ namespace.name }}
</a>
</li>
<li class="new-org" ng-if="!user.anonymous && !inReadOnlyMode">
<span class="avatar" size="30" data="{'color': '#ccc', name: '+new'}"></span>
<a href="/organizations/new">Create New Organization</a>
</li>
</ul>
</div>
</div>
<div class="col-lg-9 col-lg-pull-3 col-md-9 col-md-pull-3 col-sm-12">
<div class="repo-list-panel co-main-content-panel">
<div class="repo-list-view" namespaces="namespaces"
star-toggled="starToggled(repository)"
starred-repositories="starred_repositories"
repo-kind="image"
in-read-only-mode="inReadOnlyMode">
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,137 @@
<div class="resource-view repository-view"
resource="repositoryResource"
error-message="'Repository not found'">
<div class="page-content">
<!-- Application repository error -->
<div class="co-main-content-panel" ng-if="viewScope.repository.kind == 'application'">
<div class="error-view-element">
<h2><span class="repo-circle no-background" repo="viewScope.repository"></span>{{ viewScope.repository.namespace }}/{{ viewScope.repository.name }}</h2>
<h3>This name refers to an <strong>application</strong> repository</h3>
<div style="margin-bottom: 20px;">
View the <a href="/application/{{ viewScope.repository.namespace }}/{{ viewScope.repository.name }}/">{{ viewScope.repository.namespace }}/{{ viewScope.repository.name }} application</a>
</div>
</div>
</div>
<!-- Image repository view -->
<div ng-if="viewScope.repository.kind == 'image'">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/repository">
Repositories
</a>
</span>
<span class="cor-title-content">
<span class="repo-circle no-background hidden-xs" repo="viewScope.repository"></span>
{{ namespace }} / {{ name }}
<span class="repo-star hidden-xs" repository="viewScope.repository" ng-if="!user.anonymous"></span>
</span>
</div>
<cor-tab-panel orientation="vertical" cor-nav-tabs>
<cor-tabs>
<cor-tab tab-title="Information" tab-id="info"
tab-init="showInfo()">
<i class="fa fa-info-circle"></i>
</cor-tab>
<cor-tab tab-title="Tags" tab-id="tags" id="tagsTab"
tab-init="showTags()">
<i class="fa fa-tags"></i>
</cor-tab>
<cor-tab tab-title="Tag History" tab-id="history" id="tagHistoryTab"
tab-init="showHistory()">
<i class="fa fa-history"></i>
</cor-tab>
<cor-tab tab-title="Builds" tab-id="builds" id="buildsTab"
tab-init="showBuilds()"
quay-show="viewScope.repository.can_write && Features.BUILD_SUPPORT">
<i class="fa fa-tasks"></i>
</cor-tab>
<!-- Admin Only Tabs -->
<cor-tab tab-title="Usage Logs" tab-id="logs" tab-init="showLogs()"
ng-show="viewScope.repository.can_admin">
<i class="fa fa-bar-chart"></i>
</cor-tab>
<cor-tab tab-title="Mirroring"
tab-id="repository-mirror"
tab-init="showMirroring()"
quay-show="viewScope.repository.can_admin && Features.REPO_MIRROR">
<i class="fa fa-refresh"></i> <!-- In FontAwesome > 4.x, this will be `fa-sync` -->
</cor-tab>
<cor-tab tab-title="Settings" tab-id="settings" id="settingsTab"
tab-init="showSettings()"
ng-show="viewScope.repository.can_admin">
<i class="fa fa-gear"></i>
</cor-tab>
</cor-tabs>
<cor-tab-content>
<!-- Information -->
<cor-tab-pane id="info">
<div class="repo-panel-info"
repository="viewScope.repository"
builds="viewScope.builds"
is-enabled="infoShown"></div>
</cor-tab-pane>
<!-- Tags -->
<cor-tab-pane id="tags">
<div class="repo-panel-tags"
repository="viewScope.repository"
repository-tags="viewScope.repositoryTags"
tags-loading="viewScope.tagsLoading"
image-loader="viewScope.imageLoader"
selected-tags="viewScope.selectedTags"
history-filter="viewScope.historyFilter"
is-enabled="tagsShown"></div>
</cor-tab-pane>
<!-- Tag History -->
<cor-tab-pane id="history">
<h3 class="tab-header">Tag History</h3>
<div class="repo-tag-history"
repository="viewScope.repository"
repository-tags="viewScope.repositoryTags"
filter="viewScope.historyFilter"
image-loader="viewScope.imageLoader"
is-enabled="historyShown"></div>
</cor-tab-pane>
<!-- Builds -->
<cor-tab-pane id="builds">
<div class="repo-panel-builds"
repository="viewScope.repository"
builds="viewScope.builds"
is-enabled="buildsShown"></div>
</cor-tab-pane>
<!-- Usage Logs -->
<cor-tab-pane id="logs" ng-if="viewScope.repository.can_admin">
<div class="logs-view" repository="viewScope.repository" makevisible="logsShown"></div>
</cor-tab-pane>
<!-- Repository Mirroring -->
<cor-tab-pane id="repository-mirror"
ng-if="viewScope.repository.can_admin"
quay-show="Features.REPO_MIRROR">
<div class="repo-panel-mirror"
repository="viewScope.repository"
is-enabled="mirrorShown"></div>
</cor-tab-pane>
<!-- Settings -->
<cor-tab-pane id="settings" ng-if="viewScope.repository.can_admin">
<div class="repo-panel-settings" repository="viewScope.repository"
is-enabled="settingsShown"></div>
</cor-tab-pane>
</cor-tab-content>
</cor-tab-panel>
</div>
</div>
</div>

View file

@ -0,0 +1,50 @@
<div class="cor-container search">
<div class="search-top-bar">
<search-box query="currentQuery" clear-on-search="false"></search-box>
</div>
<div class="search-results-section">
<h5>Applications and Repositories</h5>
<div class="resource-view" resource="resultsResource" error-message="'Could not search results'">
<div class="empty" ng-if="!results.length">
<div class="empty-primary-msg">No matching applications or repositories found</div>
<div class="empty-secondary-msg">
Please try changing your query.
</div>
</div>
<ol class="search-results" start="{{ startIndex + 1 }}">
<li ng-repeat="result in results">
<div class="search-result-box">
<span class="star-count">
<span class="star-count-number">{{ result.stars }}</span>
<i class="star-icon starred fa fa-star"></i>
</span>
<h4>
<i class="fa fa-hdd-o" ng-if="result.kind == 'repository'"></i>
<i class="fa ci-appcube" ng-if="result.kind == 'application'"></i>
<a href="{{ result.href }}">{{ result.namespace.name }}/{{ result.name }}</a>
</h4>
<p class="description">
<markdown-view content="result.description"
first-line-only="true"></markdown-view>
</p>
<p class="result-info-bar">
<span class="info-span">Last Modified: <time-ago datetime="result.last_modified * 1000"></time-ago></span>
<span class="info-span activity">
activity
<span class="strength-indicator" value="::result.popularity"
maximum="::maxPopularity"
log-base="10"></span>
</span>
</p>
</div>
</li>
</ol>
<div class="page-navigation-wrapper">
<a class="btn btn-default" ng-click="previousPage()" ng-if="currentPage > 1">Previous Page</a>
<a class="btn btn-default" ng-click="nextPage()" ng-if="showNextButton">Next Page</a>
<span class="search-max-results-info" ng-if="showMaxResultsHelpText">You've reached the maximum number of viewable results. Please refine your search.</span>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,44 @@
<div class="cor-container">
<div class="row">
<div class="col-md-12">
<h1>Quay Security</h1>
<p>We understand that when you upload one of your repositories to Quay that you are trusting us with some potentially very sensitive data. On this page we will lay out our security features and practices to help you make an informed decision about whether you can trust us with your data.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>SSL Everywhere</h3>
<p>We expressly forbid connections to Quay using unencrypted HTTP traffic. This helps keep your data and account information safe on the wire. Our SSL traffic is decrypted on our application servers, so your traffic is encrypted even within the datacenter. We use a 4096-bit RSA key, and after the key exchange is complete, traffic is transferred using 256-bit AES, for the maximum encryption strength.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Encryption</h3>
<p>Our binary data is currently stored in Amazon's <a href="http://aws.amazon.com/s3/">S3</a> service. We use HTTPS when transferring your data internally between our application servers and S3, so your data is never exposed in plain text on the internet. We use their <a href="http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingServerSideEncryption.html">server side encryption</a> to protect your data while stored at rest in their data centers.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Passwords</h3>
<p>There have been a number of high profile leaks recently where companies have been storing their customers' passwords in plain text, an unsalted hash, or a <a href="http://en.wikipedia.org/wiki/Salt_(cryptography)">salted hash</a> where every salt is the same. At Quay we use the <a href="http://en.wikipedia.org/wiki/Bcrypt">bcrypt</a> algorithm to generate a salted hash from your password, using a unique salt for each password. This method of storage is safe against <a href="http://en.wikipedia.org/wiki/Rainbow_table">rainbow attacks</a> and is obviously superior to plain-text storage. Your credentials are also never written in plain text to our application logs, a leak that is commonly overlooked.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Access Controls</h3>
<p>Repositories will only ever be shared with people to whom you delegate access. Repositories created from the Docker command line are private by default and must be made public with an explicit action in the Quay UI. We have a test suite which is run before every code push which tests all methods which expose private data with all levels of access to ensure nothing is accidentally leaked.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Firewalls</h3>
<p>Our application servers and database servers are all protected with firewall settings that only allow communication with known hosts and host groups on sensitive ports (e.g. SSH). None of our servers have SSH password authentication enabled, preventing brute force password attacks.</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Data Resilience</h3>
<p>While not related directly to security, many of you are probably worried about whether you can depend on the data you store in Quay. All binary data that we store is stored in Amazon S3 at the highest redundancy level, which Amazon claims provides <a href="http://aws.amazon.com/s3/faqs/#How_is_Amazon_S3_designed_to_achieve_99.999999999%_durability">11-nines of durability</a>. Our service metadata (e.g. logins, tags, teams) is stored in a database which is backed up nightly, and backups are preserved for 7 days.</p>
</div>
</div>
</div>

View file

@ -0,0 +1,5 @@
<div class="cor-container signin-container">
<div class="row">
<div class="user-setup" redirect-url="redirectUrl"></div>
</div>
</div>

View file

@ -0,0 +1,3 @@
<div ng-show="test">
{{ test }}
</div>

View file

@ -0,0 +1,165 @@
<div class="super-user">
<div class="cor-loader" ng-show="!configStatus"></div>
<div class="page-content" quay-show="Features.SUPER_USERS && configStatus == 'ready'">
<div class="cor-title">
<span class="cor-title-link"></span>
<span class="cor-title-content">Red Hat Quay Management</span>
</div>
<cor-tab-panel orientation="vertical" cor-nav-tabs>
<cor-tabs>
<cor-tab tab-title="Manage Users"
tab-id="users" tab-init="loadUsers()">
<i class="fa fa-group"></i>
</cor-tab>
<cor-tab tab-title="Manage Organizations"
tab-id="organizations" tab-init="loadOrganizations()">
<i class="fa fa-sitemap"></i>
</cor-tab>
<cor-tab tab-title="Manage Service Keys"
tab-id="servicekeys" tab-init="loadServiceKeys()">
<i class="fa fa-key"></i>
</cor-tab>
<cor-tab tab-title="Change Log" tab-id="change-log" tab-init="getChangeLog()">
<i class="fa fa-rss"></i>
</cor-tab>
<cor-tab tab-title="Usage Logs" tab-id="logs" tab-init="loadUsageLogs()">
<i class="fa fa-bar-chart"></i>
</cor-tab>
<cor-tab tab-title="Globally visible user messages" tab-id="message-of-the-day"
tab-init="loadMessageOfTheDay()">
<i class="fa fa-newspaper-o"></i>
</cor-tab>
<cor-tab tab-title="Build Logs" tab-id="super-user-build-logs"
tab-init="loadSuperUserBuildLogs()"
quay-show="Features.BUILD_SUPPORT">
<i class="fa fa-history"></i>
</cor-tab>
</cor-tabs>
<cor-tab-content>
<!-- Super user build logs tab-->
<cor-tab-pane id="super-user-build-logs">
<div class="super-user-build-logs" is-enabled="superUserBuildLogsActive"></div>
</cor-tab-pane> <!-- Super user build logs tab -->
<!-- Messages tab -->
<cor-tab-pane id="message-of-the-day">
<div class="global-message-tab" is-enabled="globalMessagesActive"></div>
</cor-tab-pane> <!-- Messages tab -->
<!-- Service keys tab -->
<cor-tab-pane id="servicekeys">
<div class="service-keys-manager" is-enabled="serviceKeysActive"></div>
</cor-tab-pane>
<!-- Logs tab -->
<cor-tab-pane id="logs">
<div class="logsView" makevisible="logsCounter" all-logs="true"></div>
</cor-tab-pane> <!-- /logs tab-->
<!-- Change Log tab -->
<cor-tab-pane id="change-log">
<h3 style="margin-top: 0px;">Change Log</h3>
<div class="cor-loader" ng-if="!changeLog"></div>
<markdown-view ng-if="changeLog"
content="changeLog.log" ></markdown-view>
</cor-tab-pane> <!-- /change-log tab-->
<!-- Organizations tab -->
<cor-tab-pane id="organizations">
<div class="resource-view" resource="organizationsResource"
error-message="'Could not load organizations'">
<div class="manager-header" header-title="Organizations">
</div>
<div class="co-top-bar">
<span class="co-filter-box">
<span class="page-controls" total-count="orderedOrgs.entries.length" current-page="options.page" page-size="orgsPerPage"></span>
<input class="form-control" type="text" ng-model="options.filter" placeholder="Filter Organizations..." style="margin-right: 10px;">
</span>
</div>
<table class="cor-table" ng-if="orderedOrgs.entries.length && !isLoading">
<thead>
<td style="width: 24px;"></td>
<td ng-class="tablePredicateClass('name', options.predicate, options.reverse)">
<a ng-click="orderBy('name')">Name</a>
</td>
<td ng-class="tablePredicateClass('email', options.predicate, options.reverse)"
ng-if="Features.MAILING">
<a ng-click="orderBy('email')">Admin Email</a>
</td>
<td style="width: 24px;"></td>
</thead>
<tr ng-repeat="current_org in orderedOrgs.entries | slice
:(orgsPerPage * options.page)
:(orgsPerPage * (options.page + 1))"
class="org-row">
<td>
<span class="avatar" data="current_org.avatar" size="24"></span>
</td>
<td>
{{ current_org.name }}
</td>
<td ng-if="Features.MAILING">
<a href="mailto:{{ current_org.email }}">{{ current_org.email }}</a>
</td>
<td style="text-align: center;">
<span class="cor-options-menu" ng-show="!inReadOnlyMode">
<span class="cor-option" option-click="askRenameOrganization(current_org)">
<i class="fa fa-arrow-right"></i> Rename Organization
</span>
<span class="cor-option" option-click="askDeleteOrganization(current_org)">
<i class="fa fa-times"></i> Delete Organization
</span>
<span class="cor-option" option-click="askTakeOwnership(current_org)">
<i class="fa fa-bolt"></i> Take Ownership
</span>
</span>
</td>
</tr>
</table>
</div> <!-- /resource -->
</cor-tab-pane> <!-- organizations tab -->
<!-- Users tab -->
<cor-tab-pane id="users" class="tab-pane active">
<div class="manage-user-tab" is-enabled="manageUsersActive"></div>
</cor-tab-pane> <!-- users-tab -->
</cor-tab-content>
</cor-tab-panel>
<!-- Modal message dialog -->
<div class="co-dialog modal fade" id="restartingContainerModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Container Currently Restarting</h4>
</div>
<div class="modal-body" style="padding: 20px;">
<i class="fa fa-lg fa-refresh" style="margin-right: 10px;"></i>
<span class="registry-name"></span> is currently being restarted.
<br><br>
This can take several minutes. If the container does not restart on its own,
please reexecute the <code>docker run</code> command.
</div>
<div class="modal-footer working">
<span class="cor-loader-inline"></span> Waiting for container to restart...
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="cor-confirm-dialog take-ownership-dialog"
dialog-context="takeOwnershipInfo"
dialog-action="takeOwnership(info, callback)"
dialog-title="Take Ownership"
dialog-action-title="Take Ownership">
Are you sure you want to take ownership of organization <span class="avatar" data="takeOwnershipInfo.entity.avatar" size="16"></span> {{ takeOwnershipInfo.entity.name }}?</span>
</div>
</div> <!-- /page-content -->
</div>

View file

@ -0,0 +1,225 @@
<div class="resource-view team-view" resources="[orgResource, membersResource]"
error-message="'No matching organization or team found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/organization/{{ organization.name }}?tab=teams">
<span class="avatar" size="24" data="organization.avatar" style="margin-right: 4px"></span>
{{ organization.name }}
</a>
</span>
<span class="cor-title-content">
<span class="team-title">Team</span>
<span class="avatar" data="team.avatar" size="32"></span>
<span class="team-name">{{ teamname }}</span>
</span>
</div>
<div class="co-main-content-panel">
<div class="feedback-bar" feedback="feedback"></div>
<div class="team-sync-header" ng-if="canSync && !syncInfo && !inReadOnlyMode">
<div class="section-header">Directory Synchronization</div>
<p>Directory synchronization allows this team's user membership to be backed by a group in {{ getServiceName(canSync.service) }}.</p>
<button class="btn btn-primary" ng-click="showEnableSyncing()">Enable Directory Synchronization</button>
</div>
<!-- Sync Header -->
<div ng-if="syncInfo">
<div class="co-alert co-alert-info">
This team is synchronized with a group in <strong>{{ getServiceName(syncInfo.service) }}</strong> and its user membership is therefore <strong>read-only</strong>.
</div>
<div class="team-sync-header" ng-if="syncInfo.config">
<div class="section-header">Directory Synchronization</div>
<table class="team-sync-table">
<tr>
<td>Bound to group:</td>
<td>
<div ng-if="syncInfo.service == 'ldap'">
<code>{{ syncInfo.config.group_dn }}</code>
</div>
<div ng-if="syncInfo.service == 'keystone'">
<code>{{ syncInfo.config.group_id }}</code>
</div>
</td>
</tr>
<tr>
<td>Last Updated:</td>
<td ng-if="syncInfo.last_updated"><time-ago datetime="syncInfo.last_updated"></time-ago></td>
<td ng-if="!syncInfo.last_updated" style="color: #aaa;">Never</td>
</tr>
</table>
<button class="btn btn-default" ng-click="showDisableSyncing()" ng-if="canSync && !inReadOnlyMode">Remove Synchronization</button>
<div ng-if="!canSync" class="co-alert co-alert-warning co-alert-inline">You must be an admin of this organization to disable team synchronization</div>
</div>
</div>
<!-- Description -->
<div class="section-header">Team Description</div>
<div class="team-view-header">
<div class="description">
<markdown-input content="team.description"
can-write="organization.is_admin && !inReadOnlyMode"
(content-changed)="updateForDescription($event.content)"
field-title="team description"></markdown-input>
</div>
</div>
<!-- Members -->
<div ng-show="canEditMembers && !inReadOnlyMode" style="float:right; margin-top: 10px;">
<div class="hidden-xs">
<div ng-include="'/static/directives/team-view-add.html'" style="max-width: 500px;"></div>
</div>
</div>
<div class="section-header" style="margin-bottom: 55px;">Team Members</div>
<div class="empty" ng-if="!members.length">
<div class="empty-primary-msg">This team has no members.</div>
<div class="empty-secondary-msg" ng-if="!syncInfo">
Enter a user or robot above to add or invite to the team.
</div>
<div class="empty-secondary-msg" ng-if="syncInfo">
This team is synchronized with an external group defined in {{ getServiceName(syncInfo.service) }}. To add a user to this team, add them in the backing group. To add a robot account to this team, enter them above.
</div>
</div>
<table class="co-table no-lines" ng-if="members.length">
<!-- Team Members -->
<tr class="co-table-header-row"
ng-if="(members | filter: filterFunction(false, false)).length">
<td colspan="3"><i class="fa fa-user"></i> Team Members <span ng-if="syncInfo">(defined in {{ getServiceName(syncInfo.service) }})</span></td>
</tr>
<tr class="indented-row"
ng-repeat="member in members | filter: filterFunction(false, false) | orderBy: 'name'">
<td class="user entity">
<span class="entity-reference" entity="member" namespace="organization.name"
show-avatar="true" avatar-size="24"></span>
</td>
<td class="options-col">
<span class="cor-options-menu" ng-if="canEditMembers && !syncInfo && !inReadOnlyMode">
<span class="cor-option" option-click="removeMember(member.name)">
<i class="fa fa-times"></i> Remove {{ member.name }}
</span>
</span>
</td>
</tr>
<!-- Robot Accounts -->
<tr class="co-table-header-row"
ng-if="(members | filter: filterFunction(false, true)).length">
<td colspan="3"><i class="fa ci-robot"></i> Robot Accounts</td>
</tr>
<tr class="indented-row"
ng-repeat="member in members | filter: filterFunction(false, true) | orderBy: 'name'">
<td class="user entity">
<span class="entity-reference" entity="member" namespace="organization.name"></span>
</td>
<td class="options-col">
<span class="cor-options-menu" ng-if="canEditMembers && !inReadOnlyMode">
<span class="cor-option" option-click="removeMember(member.name)">
<i class="fa fa-times"></i> Remove {{ member.name }}
</span>
</span>
</td>
</tr>
<!-- Invitations -->
<tr class="co-table-header-row"
ng-if="(members | filter: filterFunction(true, false)).length">
<td colspan="3"><i class="fa ci-invite"></i> Invited to Join</td>
</tr>
<tr class="indented-row"
ng-repeat="member in members | filter: filterFunction(true, false) | orderBy: 'name'">
<td class="user entity">
<span ng-if="member.kind != 'invite'">
<span class="entity-reference" entity="member" namespace="organization.name" show-avatar="true" avatar-size="24"></span>
</span>
<span class="invite-listing" ng-if="member.kind == 'invite'">
<span class="avatar" size="24" data="member.avatar" style="margin-right: 6px;"></span>
{{ member.email }}
</span>
</td>
<td class="options-col">
<span class="cor-options-menu" ng-if="canEditMembers && !inReadOnlyMode">
<span class="cor-option" option-click="revokeInvite(member)">
<i class="fa fa-times"></i> Revoke invite
</span>
</span>
</td>
</tr>
</table>
<!-- Add team member (mobile) -->
<div ng-show="canEditMembers && !inReadOnlyMode">
<div class="visible-xs" style="margin-top: 20px; padding-top: 10px; border-top: 1px solid #eee;">
<div class="section-header">Add team member</div>
<div ng-include="'/static/directives/team-view-add.html'" style="max-width: 500px;"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Directory binding dialog -->
<div class="cor-confirm-dialog"
dialog-context="enableSyncingInfo"
dialog-action="enableSyncing(info.config, callback)"
dialog-title="Enable Directory Syncing"
dialog-action-title="Enable Group Sync"
dialog-form="context.syncform">
<div class="co-alert co-alert-warning">Please note that once team syncing is enabled, the team's user membership from within <span class="registry-name"></span> will be read-only.</div>
<form name="context.syncform" class="co-single-field-dialog">
<div ng-switch on="enableSyncingInfo.service_info.service">
<div ng-switch-when="ldap">
Enter the distinguished name of the group, relative to <code>{{ enableSyncingInfo.service_info.base_dn }}</code>:
<input type="text" class="form-control" placeholder="Group DN" ng-model="enableSyncingInfo.config.group_dn" required>
</div>
<div ng-switch-when="keystone">
Enter the Keystone group ID:
<input type="text" class="form-control" placeholder="Group ID" ng-model="enableSyncingInfo.config.group_id" required>
</div>
</div>
</form>
</div>
<!-- Modal message dialog -->
<div class="modal fade" id="cannotChangeTeamModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Cannot change team</h4>
</div>
<div class="modal-body">
You do not have permission to change properties of this team.
</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="cannotChangeMembersModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Cannot change members</h4>
</div>
<div class="modal-body">
You do not have permission to change the members of this team.
</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 -->

143
static/partials/tos.html Normal file
View file

@ -0,0 +1,143 @@
<div class="tos container">
<h2>CoreOS Terms of Service</h2>
<h4>Last Revised: February 5, 2015</h4>
<p>These Quay Terms of Service (these “<strong>Terms</strong>”) apply to the features and functions provided by CoreOS, Inc. (“<strong>CoreOS</strong>,” “<strong>our</strong>,” or “<strong>we</strong>”) via quay.io (the “<strong>Site</strong>”) (collectively, the “<strong>Services</strong>”). By accessing or using the Services, you agree to be bound by these Terms. If you do not agree to these Terms, do not use any of the Services. The “<strong>Effective Date</strong>” of these Terms is the date you first access any of the Services.</p>
<p>If you are accessing the Services in your capacity as an employee, consultant or agent of a company (or other entity), you represent that you are an employee, consultant or agent of such company (or other entity) and you have the authority to agree (and be legally bound) on behalf of such company (or other entity) to all of the terms and conditions of these Terms.</p>
<p>For the purpose of these Terms, you and, if applicable, such company (or other entity) constitutes “<strong>Customer</strong>” or “<strong>you</strong>”.</p>
<p>CoreOS reserves the right to change or modify any of the terms and conditions contained in these Terms (or any policy or guideline of CoreOS) at any time and in its sole discretion by providing notice that these Terms have been modified. Such notice may be provided by sending an email, posting a notice on the Site, posting the revised Terms on the Site and revising the date at the top of these Terms or such other form of notice as determined by CoreOS. Any changes or modifications will be effective 30 days after providing notice that these Terms have been modified (the “<strong>Notice Period</strong>”). Your continued use of any of the Services following the Notice Period will constitute your acceptance of such changes or modifications. Therefore, you should review these Terms whenever you access the Services and at least every 30 days to make sure that you understand the terms and conditions that will apply to your use of the Services.</p>
<p>These terms form a binding agreement between you and CoreOS.</p>
<ol>
<li>
<strong>Privacy</strong>
<p>Please see CoreOS privacy policy at <a href="/privacy">https://quay.io/privacy</a> for information about how CoreOS collects, uses and discloses information about users of the Site and the Services.</p>
</li>
<li>
<strong>Registration</strong>
<p>In order to access the Services, you must complete the CoreOS registration form provided via the Site. During the registration process, you must select a CoreOS package which includes: (a) the monthly or annual period during which you can access the Services (the “<strong>Subscription Period</strong>”); and (b) the monthly or annual fee you must pay to CoreOS in exchange for your rights to the Services (the “<strong>Subscription Fees</strong>”). All such information is incorporated into these Terms by reference.</p>
<p>You agree to: (a) provide accurate, current and complete information about you as may be prompted by the registration forms via the Site (“<strong>Registration Data</strong>”); (b) maintain the security of your password; (c) maintain and promptly update the Registration Data, and any other information you provide to CoreOS, to keep it accurate, current and complete; and (d) accept all risks of unauthorized access to the Registration Data and any other information you provide to CoreOS.</p>
<p>You are responsible for safeguarding the password that you use to access the Services, and you agree to be fully responsible for activities or transactions that relate to your account and password</p>
</li>
<li>
<strong>Services</strong>
<p>Subject to the terms and conditions of these Terms, CoreOS grants you a limited, non-transferable, non-exclusive and revocable right and license to access and use the Services.</p>
</li>
<li>
<strong>Restrictions</strong>
<p>Except as expressly authorized by these Terms, you may not (a) modify, disclose, alter, translate or create derivative works of the Services, (b) license, sublicense, resell, distribute, lease, rent, lend, transfer, assign or otherwise dispose of the Services (or any components thereof), (c) use the Services to store or transmit any viruses, software routines or other code designed to permit unauthorized access, to disable, erase or otherwise harm software, hardware or data, or to perform any other harmful actions, (d) build a competitive product or service, or copy any features or functions of the Services, (e) interfere with or disrupt the integrity or performance of the Services, (f) disclose to any third party any performance information or analysis relating to the Services, (g) remove, alter or obscure any proprietary notices in or on the Services, including copyright notices, or (h) cause or permit any third party to do any of the foregoing.</p>
</li>
<li>
<strong>Your Responsibilities</strong>
<p>If you share your repository, publish images, code or content, or otherwise make (or allow any third party to make) material available by means of the Site (“<strong>Content</strong>”), you are entirely responsible for such Content of, and any harm resulting from, that Content. That is the case regardless of whether the Content in question constitutes text, graphics, an audio file, or computer software. By making Content available, you represent and warrant that:</p>
<ul>
<li>the downloading, copying and use of the Content will not infringe, violate or misappropriate any Intellectual Property Rights of any third party;</li>
<li>if your employer has rights to intellectual property you create, you have either (a) received permission from your employer to post or make available the Content, including but not limited to any software, or (b) secured from your employer a waiver as to all rights in or to the Content;</li>
<li>you have fully complied with any third-party licenses relating to the Content, and have done all things necessary to successfully pass through to end users any required terms;</li>
<li>the Content does not contain or install any viruses, worms, malware, Trojan horses or other harmful or destructive content;</li>
<li>the Content is not spam, is not randomly-generated, and does not contain unethical or unwanted commercial content designed to drive traffic to third party sites or boost the search engine rankings of third party sites, or to further unlawful acts (such as phishing) or mislead recipients as to the source of the material (such as spoofing);</li>
<li>the Content does not contain threats or incite violence, and does not violate the privacy or publicity rights of any third party;</li>
<li>your Content is not getting advertised via unwanted electronic messages such as spam links on newsgroups, email lists, other blogs and web sites, and similar unsolicited promotional methods;</li>
<li>your Content is not named in a manner that misleads your readers into thinking that you are another person or company. For example, your Contents URL or name is not the name of a person other than yourself or company other than your own; and</li>
<li>you have, in the case of Content that includes computer code, accurately categorized and/or described the type, nature, uses and effects of the materials, whether requested to do so by CoreOS or otherwise.</li>
</ul>
<p>By submitting Content or computer code to CoreOS for inclusion in your repositories, you grant CoreOS a world-wide, royalty-free, and non-exclusive license to reproduce, modify, adapt and publish the Content solely for the purpose of providing the services you request. If you delete Content, CoreOS will use reasonable efforts to remove it from the Services, but you acknowledge that caching or references to the Content may not be made immediately unavailable.</p>
<p>Without limiting any of those representations or warranties, CoreOS has the right (though not the obligation) to, in CoreOS sole discretion (a) refuse or remove any content that, in CoreOS reasonable opinion, violates any CoreOS policy or is in any way harmful or objectionable, or (b) terminate or deny access to and use of the Site to any individual or entity for any reason, in CoreOS sole discretion. CoreOS will have no obligation to provide a refund of any amounts previously paid.</p>
</li>
<li>
<strong>Fees and Payment Terms</strong>
<p>In exchange for your rights to the Services, you will pay to CoreOS the Subscription Fees. The Subscription Fees do not include taxes, and the Subscription Fees are payable in advance in accordance with your Quay Plan.</p>
<p>Unless CoreOS states otherwise, all payments must be made (a) in U.S. Dollars; and (b) by payment card via an authorized CoreOS payment processor. If you pay via a payment card, you hereby (i) authorize CoreOS (or its authorized payment processor) to make automatic recurring charges to your designated payment card number in the applicable amount of the Subscription Fees on an annual or monthly basis (as applicable) for the duration of the Subscription Period, (ii) represent and warrant that you are authorized to use and have fees charged to the payment card number you provide to CoreOS, and (iii) understand that you may withdraw this consent by emailing CoreOS at <a href="mailto:support@quay.io">support@quay.io</a>. <strong>Accounts can be canceled at any time in the Plan and Usage section of your Account Settings. No refunds will be issued (unless expressly stated otherwise).</strong></p>
<p>Notwithstanding any terms to the contrary in these Terms, CoreOS, at its sole discretion, may modify its pricing during any Subscription Period and such modifications will be effective as of the directly subsequent Subscription Period.</p>
<p>Interest on any late payments will accrue at the rate of 1.5% per month, or the highest rate permitted by law, whichever is lower, from the date such amount is due until the date such amount is paid in full. You will be responsible for, and will pay all sales and similar taxes on, all license fees and similar fees levied upon the provision of the Services provided under these Terms, excluding only taxes based solely on CoreOS net income. You will indemnify and hold CoreOS harmless from and against any and all such taxes and related amounts levied upon the provision of the Services and any costs associated with the collection or withholding thereof, including penalties and interest.</p>
</li>
<li>
<strong>Disclaimer</strong>
<p>COREOS DISCLAIMS ANY AND ALL REPRESENTATIONS OR WARRANTIES (EXPRESS OR IMPLIED, ORAL OR WRITTEN) WITH RESPECT TO THESE TERMS, SERVICES AND ANY OPEN SOURCE SOFTWARE (AS DEFINED BELOW), WHETHER ALLEGED TO ARISE BY OPERATION OF LAW, BY REASON OF CUSTOM OR USAGE IN THE TRADE, BY COURSE OF DEALING OR OTHERWISE. NOTWITHSTANDING ANY TERMS TO THE CONTRARY IN THESE TERMS, COMPANY ACKNOWLEDGES AND AGREES THAT COREOS MAY MODIFY THE FEATURES OF THE SERVICES FROM TIME-TO-TIME AT COREOS SOLE DISCRETION.</p>
</li>
<li>
<strong>Indemnification Obligations</strong>
<p>You agree, at your sole expense, to defend, indemnify and hold CoreOS (and its directors, officers, employees, consultants and agents) harmless from and against any and all actual or threatened suits, actions, proceedings (at law or in equity), claims, damages, payments, deficiencies, fines, judgments, settlements, liabilities, losses, costs and expenses (including, but not limited to, reasonable attorneys fees, costs, penalties, interest and disbursements) for any death, injury, property damage caused by, arising out of, resulting from, attributable to or in any way incidental to any of your Content or any actual or alleged breach of any of your obligations under these Terms (including, but not limited to, any actual or alleged breach of any of your representations or warranties as set forth in these Terms).</p>
</li>
<li>
<strong>Limitation of Liability</strong>
<p>IN NO EVENT WILL (A) COREOS TOTAL LIABILITY ARISING OUT OF OR RELATED TO THESE TERMS EXCEED THE TOTAL AMOUNT PAID BY YOU TO COREOS UNDER THESE TERMS THE SIX MONTHS IMMEDIATELY PRIOR TO THE ACCRUAL OF THE FIRST CLAIM, AND (B) COREOS BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY LOSS OF PROFITS, LOSS OF USE, LOSS OF REVENUE, LOSS OF GOODWILL, ANY INTERRUPTION OF BUSINESS, OR ANY INDIRECT, SPECIAL, INCIDENTAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES OF ANY KIND ARISING OUT OF, OR IN CONNECTION WITH THESE TERMS, WHETHER IN CONTRACT, TORT, STRICT LIABILITY OR OTHERWISE, EVEN IF SUCH PARTY HAS BEEN ADVISED OR IS OTHERWISE AWARE OF THE POSSIBILITY OF SUCH DAMAGES. MULTIPLE CLAIMS WILL NOT EXPAND THIS LIMITATION. THIS SECTION (LIMITATION OF LIABILITY) WILL BE GIVEN FULL EFFECT EVEN IF ANY REMEDY SPECIFIED IN THESE TERMS IS DEEMED TO HAVE FAILED OF ITS ESSENTIAL PURPOSE.</p>
</li>
<li>
<strong>Ownership</strong>
<p>As between the parties and subject to Section 5 (Your Responsibilities), you own all right, title and interest in and to the Content and any and all Intellectual Property Rights (as defined below) embodied in or related to the foregoing. As between the parties and subject to Section 3 (Services), CoreOS owns all right, title and interest in and to the Services and any and all Intellectual Property Rights (as defined below) embodied in or related to the foregoing. CoreOS reserves all rights not expressly granted in these Terms, and no licenses are granted by CoreOS to you or any other party under these Terms, whether by implication, estoppel or otherwise, except as expressly set forth in these Terms. For the purpose of these Terms, “<strong>Intellectual Property Rights</strong>” means all patents, copyrights, moral rights, trademarks, trade secrets and any other form of intellectual property rights recognized in any jurisdiction, including applications and registrations for any of the foregoing.</p>
</li>
<li>
<strong>Term, Termination and Effect of Termination</strong>
<p>Unless earlier terminated as set forth in these Terms, the term of these Terms commences upon the Effective Date and continues for the Subscription Period, and thereafter the term of these Terms automatically renews for one or more additional Subscription Periods unless a party terminates these Terms with no less than 15 days advance written notice prior to the close of the then-current term. Further, CoreOS may terminate or deny access to and use of the Services if CoreOS reasonably believes you have violate any of the terms or conditions of these Terms. Upon any termination of these Terms, your rights to the Services will immediately cease.</p>
</li>
<li>
<strong>Copyright Policy</strong>
<p>CoreOS users may report content that appears on/via the Site or Services to CoreOS that he/she thinks violates these Terms, and CoreOS may remove such content, suspend or terminate the account of the user who made posted such content and/or take additional action to enforce these Terms against such user.</p>
<p>Also, in accordance with the Digital Millennium Copyright Act (DMCA) and other applicable law, CoreOS has adopted a policy of terminating, in appropriate circumstances and at our discretion, account holders who are deemed to be repeat infringers. CoreOS also may, at its discretion, limit access to the Services and terminate the accounts of any users who infringe any intellectual property rights of others, whether or not there is any repeat infringement.</p>
<p>If you think that anything on the Services infringes upon any copyright that you own or control, you may file a notification with CoreOS Designated Agent as set forth below:</p>
<table border=0>
<tr><td>Designated Agent:</td><td>DMCA Agent</td></tr>
<tr><td>Address of Designated Agent:</td><td>3043 Mission Street, San Francisco, CA 94110</td></tr>
<tr><td>Telephone Number of Designated Agent:</td><td>(800) 774-3507</td></tr>
<tr><td>Fax Number of Designated Agent:</td><td>(415) 580-7362</td></tr>
<tr><td>Email Address of Designated Agent:</td><td>support@quay.io</td></tr>
</table>
<p>Please see <a href="http://www.copyright.gov/title17/92chap5.html#512">17 U.S.C. § 512(c)(3)</a> for the requirements of a proper notification. If you knowingly misrepresent that any material or activity is infringing, you may be liable for any damages, including costs and attorneys fees, CoreOS or the alleged infringer incurs because we relied on the misrepresentation when removing or disabling access to the material or activity.</p>
</li>
<li>
<strong>Feedback</strong>
<p>Any suggestions, comments, or other feedback provided by you to CoreOS with respect to the Services or CoreOS (collectively, “<strong>Feedback</strong>”) will constitute confidential information of CoreOS. CoreOS will be free to use, disclose, reproduce, license, and otherwise distribute and exploit the Feedback provided to it as it sees fit, entirely without obligation or restriction of any kind, on account of intellectual property rights or otherwise.</p>
</li>
<li>
<strong>Links</strong>
<p>You are granted a limited, non-exclusive right to create a text hyperlink to the Services for noncommercial purposes, provided such link does not portray CoreOS or any of its products and services in a false, misleading, derogatory, or defamatory manner and that the linking site does not contain any material that is offensive, illegal, harassing, or otherwise objectionable. This limited right may be revoked at any time. CoreOS makes no claim or representation regarding, and accepts no responsibility for, the quality, content, nature, or reliability of third-party sites accessible by link from the Services or Site. CoreOS provides these links to you only as a convenience, and the inclusion of any link does not imply affiliation, endorsement, or adoption by CoreOS of the corresponding site or any information contained in (or made available via) that site. When you leave the Site, CoreOS terms and policies no longer govern. You should review the applicable terms and policies, including privacy and data-gathering practices, of any site to which you navigate from the Site.</p>
</li>
<li>
<strong>Trademarks</strong>
<p>CoreOS name, trademarks, logos, and any other CoreOS product, service name, or slogan included in the Site are property of CoreOS and may not be copied, imitated, or used (in whole or in part) without CoreOS prior written consent. The look and feel of the Site, including all custom graphics, button icons, and scripts constitute service marks, trademarks, or trade dress of CoreOS and may not be copied, imitated, or used (in whole or in part) without CoreOS prior written consent. All other trademarks, registered trademarks, product names, and company names or logos mentioned in the Site (“<strong>Third-Party Trademarks</strong>”) are the property of their respective owners, and the use of such Third-Party Trademarks inures to the benefit of each owner. The use of such Third-Party Trademarks is intended to denote interoperability and does not constitute an affiliation by CoreOS and its licensors with such company or an endorsement or approval by such company of CoreOS or its licensors or their respective products or services.</p>
</li>
<li>
<strong>General Provisions</strong>
<p/>
<dl>
<dt>Entire Agreement</dt>
<dd>
These Terms (together with all terms incorporated in by reference) are the complete and exclusive statement of the mutual understanding of the parties and supersedes and cancels all previous written and oral agreements and communications relating to the subject matter of these Terms.
</dd>
<dt>Governing Law and Venue</dt>
<dd>
These Terms will be governed by and construed in accordance with the laws of the State of California applicable to agreements made and to be entirely performed within the State of California, without resort to its conflict of law provisions. The federal court in San Mateo County, California will be the jurisdiction in which any suits should be filed if they relate to these Terms. Prior to the filing or initiation of any action or proceeding relating to these Terms, the parties must participate in good faith mediation in San Mateo County, California. If a party initiates any proceeding regarding these Terms, the prevailing party to such proceeding is entitled to reasonable attorneys fees and costs for claims arising out of these Terms.
</dd>
<dt>Publicity</dt>
<dd>
You consent to CoreOS use of your name and/or logo on the CoreOS website, identifying you as a customer of CoreOS and describing your use of the Services notwithstanding any terms to the contrary in these Terms. You agree that CoreOS may issue a press release identifying you as customer of CoreOS.
</dd>
<dt>Assignment</dt>
<dd>
Neither these Terms nor any right or duty under these Terms may be transferred, assigned or delegated by you, by operation of law or otherwise, without the prior written consent of CoreOS, and any attempted transfer, assignment or delegation without such consent will be void and without effect. CoreOS may freely transfer, assign or delegate these Terms or its rights and duties under these Terms. Subject to the foregoing, these Terms will be binding upon and will inure to the benefit of the parties and their respective representatives, heirs, administrators, successors and permitted assigns.
</dd>
<dt>Amendments and Waivers</dt>
<dd>
Unless expressly stated otherwise stated in your standard service terms, no modification, addition or deletion, or waiver of any rights under these Terms will be binding on a party unless clearly understood by the parties to be a modification or waiver and signed by a duly authorized representative of each party. No failure or delay (in whole or in part) on the part of a party to exercise any right or remedy hereunder will operate as a waiver thereof or effect any other right or remedy. All rights and remedies hereunder are cumulative and are not exclusive of any other rights or remedies provided hereunder or by law. The waiver of one breach or default or any delay in exercising any rights will not constitute a waiver of any subsequent breach or default.
</dd>
<dt>Electronic Communications</dt>
<dd>
CoreOS may choose to electronically deliver all communications with you, which may include email to the email address you provide to CoreOS. CoreOS electronic communications to you may transmit or convey information about action taken on your request, portions of your request that may be incomplete or require additional explanation, any notices required under applicable law and any other notices. You agree to do business electronically with CoreOS and to receive electronically all current and future notices, disclosures, communications and information and that the aforementioned electronic communications satisfy any legal requirement that such communications be in writing. An electronic notice will be deemed to have been received on the day of receipt as evidenced by such email.
</dd>
<dt>Severability</dt>
<dd>
If any provision of these Terms is invalid, illegal, or incapable of being enforced by any rule of law or public policy, all other provisions of these Terms will nonetheless remain in full force and effect so long as the economic and legal substance of the transactions contemplated by these Terms is not affected in any manner adverse to any party. Upon such determination that any provision is invalid, illegal, or incapable of being enforced, the parties will negotiate in good faith to modify these Terms so as to effect the original intent of the parties as closely as possible in an acceptable manner to the end that the transactions contemplated hereby are fulfilled.
</dd>
<dt>Force Majeure</dt>
<dd>
Except for payments due under these Terms, neither party will be responsible for any failure to perform or delay attributable in whole or in part to any cause beyond its reasonable control, including, but not limited to, acts of God (fire, storm, floods, earthquakes, etc.), civil disturbances, disruption of telecommunications, disruption of power or other essential services, interruption or termination of service by any service providers being used by CoreOS to host the Services or to link its servers to the Internet, labor disturbances, vandalism, cable cut, computer viruses or other similar occurrences, or any malicious or unlawful acts of any third party.
</dd>
<dt>Notice for California Users</dt>
<dd>
If you are a California resident, you may have these Terms mailed to you electronically by sending a letter to the foregoing address with your electronic mail address and a request for these Terms. Under California Civil Code Section 1789.3, California Website users are entitled to the following specific consumer rights notice: The Complaint Assistance Unit of the Division of Consumer Services of the California Department of Consumer Affairs may be contacted in writing at 1625 N. Market Blvd., Suite S-202, Sacramento, California 95834, or by telephone at (800) 952-5210.
</dd>
</dl>
</li>
</ol>
</div>

11
static/partials/tour.html Normal file
View file

@ -0,0 +1,11 @@
<div class="tour-section-container">
<ul class="tour-sections">
<li ng-class="kind == '' || kind == 'features' ? 'active' : ''"><a href="/tour/features">Features</a></li>
<li ng-class="kind == 'organizations' ? 'active' : ''"><a href="/tour/organizations">Teams and Organizations</a></li>
<li ng-class="kind == 'enterprise' ? 'active' : ''" quay-require="['BILLING']"><a href="/tour/enterprise">Enterprise</a></li>
</ul>
</div>
<div class="cor-container">
<div class="tour-content" kind="kind"></div>
</div>

View file

@ -0,0 +1,58 @@
<div class="resource-view trigger-setup-element"
resources="[repositoryResource, triggerResource]"
error-message="'Build trigger not found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link">
<a class="back-link" href="/repository/{{ repository.namespace }}/{{ repository.name }}?tab=builds">
<i class="fa fa-hdd-o" style="margin-right: 4px"></i>
{{ repository.namespace }}/{{ repository.name }}
</a>
</span>
<span class="cor-title-content">
<i class="fa" ng-class="getTriggerIcon()"></i>
Setup Build Trigger: {{ getTriggerId() }}
</span>
</div>
<div class="co-main-content-panel" ng-show="state != 'activated' && trigger.is_active">
<div class="co-alert co-alert-info">
Trigger has already been activated.
</div>
</div>
<div class="co-main-content-panel" ng-show="state == 'activated' || !trigger.is_active">
<!-- state = activated -->
<div class="activated" ng-if="state == 'activated'">
<div class="row">
<div class="col-md-offset-3 col-md-6 col-sm-12 col-lg-6 content">
<h3>Trigger has been successfully activated</h3>
<div class="co-alert co-alert-warning">
<strong>Please note:</strong> If the trigger continuously fails to build, it will be automatically
disabled. It can be re-enabled from the build trigger list.
</div>
<div class="credentials" trigger="trigger"></div>
<div class="button-bar">
<a href="/repository/{{ repository.namespace }}/{{ repository.name }}?tab=builds">
Return to {{ repository.namespace }}/{{ repository.name }}
</a>
</div>
</div>
</div>
</div> <!-- /state = activated -->
<!-- state = managing or activating -->
<div ng-if="(state == 'managing' || state == 'activating') && trigger"
ng-class="{'activating': state == 'activating'}">
<manage-trigger githost="trigger.service"
trigger="trigger"
repository="repository"
(activate-trigger)="activateTrigger($event)"></manage-trigger>
<div class="activating-message" ng-show="state == 'activating'">
<div class="cor-loader-inline"></div><b>Completing setup of the build trigger</b>
</div>
</div> <!-- /state = managing -->
</div> <!-- /co-main-content-panel -->
</div>
</div>

View file

@ -0,0 +1,10 @@
<div class="tutorial-view page-content">
<div class="cor-title">
<span class="cor-title-link"></span>
<span class="cor-title-content">Tutorial</span>
</div>
<div class="co-main-content-panel">
<div class="angular-tour-ui" tour="tour" inline="true"></div>
</div>
</div>

View file

@ -0,0 +1,88 @@
<div class="cor-loader-inline" ng-if="!user || user.anonymous || state == 'updating'"></div>
<!-- Confirm username -->
<div class="update-user" ng-show="hasPrompt(user, 'confirm_username') && state != 'updating'">
<h2>Confirm Username</h2>
<p>
The username <strong>{{ user.username }}</strong> was automatically generated to conform to the
Docker CLI guidelines for use as a namespace in <span class="registry-title"></span>.
</p>
<p>Please confirm the selected username or enter a different username below:</p>
<form name="usernameForm" ng-submit="updateUser({'username': username})">
<div class="namespace-input" binding="username" back-incompat-message="backIncompatMessage"
namespace-title="Username" style="margin-bottom: 20px;"
has-external-error="state == 'existing'"></div>
<input type="submit" class="btn btn-primary"
ng-disabled="usernameForm.$invalid || state != 'confirmed'"
value="Confirm Username">
<span class="cor-loader-inline" ng-show="state == 'confirming'"></span>
<span class="username-status" ng-show="state == 'confirmed' && !backIncompatMessage">
<i class="fa fa-check-circle"></i> Username valid
</span>
<span class="username-status" ng-show="state == 'existing'">
<i class="fa fa-ban"></i> Username already taken
</span>
<span class="username-status" ng-show="state == 'error'">
<i class="fa fa-exclamation-triangle"></i> Could not check username
</span>
<span class="username-status" ng-show="state == 'editing' && usernameForm.$invalid">
Usernames must be alphanumeric and be at least four characters in length
</span>
<span class="username-status" ng-show="state == 'confirmed' && backIncompatMessage">
<i class="fa fa-exclamation-triangle"></i>{{ backIncompatMessage }}
</span>
</form>
</div>
<!-- Enter metadata -->
<div class="update-user" ng-show="!hasPrompt(user, 'confirm_username') && (hasPrompt(user, 'enter_name') || hasPrompt(user, 'enter_company')) && state != 'updating'">
<h2>Tell us a bit more about yourself</h2>
<div>This information will be displayed in your user profile.</div>
<form name="metadataForm" ng-submit="updateUser(metadata)" style="margin-top: 20px;">
<div class="form-group nested">
<label for="givenName">Given Name</label>
<div class="field-row">
<span class="field-container">
<input type="text" class="form-control" placeholder="Given Name" ng-model="metadata.given_name" name="givenName">
</span>
</div>
</div>
<div class="form-group nested">
<label for="familyName">Family Name</label>
<div class="field-row">
<span class="field-container">
<input type="text" class="form-control" placeholder="Family Name" ng-model="metadata.family_name" name="familyName">
</span>
</div>
</div>
<div class="form-group nested">
<label for="company">Company</label>
<div class="field-row">
<span class="field-container">
<input type="text" class="form-control" placeholder="Company name" ng-model="metadata.company" name="company"></span>
</span>
</div>
</div>
<div class="form-group nested">
<label for="location">Location</label>
<div class="field-row">
<span class="field-container">
<input type="text" class="form-control" placeholder="Location" ng-model="metadata.location" name="location"></span>
</span>
</div>
</div>
<div style="margin-top: 20px">
<input type="submit" class="btn btn-primary" value="Save Details"
ng-disabled="!metadata.name && !metadata.company">
<button class="btn btn-default"
ng-click="updateUser({'company': '', 'name': ''})">
No thanks</button>
</div>
</form>
</div>

View file

@ -0,0 +1,267 @@
<div class="resource-view user-view"
resource="userResource"
error-message="'User not found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link"></span>
<span class="cor-title-content">
<span class="avatar" size="32" data="context.viewuser.avatar"></span>
<span class="user-name">{{ context.viewuser.username }}</span>
</span>
<span class="cor-title-action" ng-if="context.viewuser.is_me && !inReadOnlyMode">
<a href="/new/?namespace={{ context.viewuser.username }}">
<i class="fa fa-plus" data-title="Create new repository"></i>
Create New Repository
</a>
</span>
</div>
<div class="co-main-content-panel user-repo-list" ng-if="!context.viewuser.is_me">
<div class="repo-list-view padded" namespaces="[context.viewuser]"
in-read-only-mode="inReadOnlyMode">&nbsp;</div>
</div>
<cor-tab-panel ng-if="context.viewuser.is_me"
orientation="vertical"
cor-nav-tabs>
<cor-tabs quay-show="context.viewuser.is_me">
<cor-tab tab-active="true" tab-title="Repositories" tab-id="repos">
<i class="fa fa-hdd-o"></i>
</cor-tab>
<cor-tab tab-title="Robot Accounts" tab-init="showRobots()" tab-id="robots">
<i class="fa ci-robot"></i>
</cor-tab>
<cor-tab tab-title="External Logins And Applications" tab-id="external"
tab-init="showApplications()" quay-show="!hasSingleSignin && !inReadOnlyMode">
<i class="fa fa-external-link-square"></i>
</cor-tab>
<cor-tab tab-title="Usage Logs" tab-id="logs" tab-init="showLogs()"
quay-show="Features.USER_LOG_ACCESS">
<i class="fa fa-bar-chart"></i>
</cor-tab>
<cor-tab tab-title="User Settings" tab-id="settings" tab-init="showBilling()">
<i class="fa fa-gears"></i>
</cor-tab>
</cor-tabs>
<cor-tab-content>
<!-- Repositories -->
<cor-tab-pane id="repos">
<div class="repo-list-view" namespaces="[context.viewuser]"
in-read-only-mode="inReadOnlyMode"><h3>Repositories</h3></div>
</cor-tab-pane>
<!-- Robot Accounts -->
<cor-tab-pane id="robots">
<div class="robots-manager" user="viewuser" is-enabled="showRobotsCounter"></div>
</cor-tab-pane>
<!-- Usage Logs -->
<cor-tab-pane id="logs">
<div class="logs-view" user="viewuser" makevisible="showLogsCounter"></div>
</cor-tab-pane>
<!-- External Logins And Applications -->
<cor-tab-pane id="external" quay-show="!hasSingleSignin && !inReadOnlyMode">
<div class="external-logins-manager" user="viewuser"
quay-show="!hasSingleSignin"></div>
<div style="margin: 50px" quay-show="!hasSingleSignin">
</div>
<div class="authorized-apps-manager" user="viewuser" is-enabled="showAppsCounter"></div>
</cor-tab-pane>
<!-- Settings -->
<cor-tab-pane id="settings">
<!-- Encrypted Password -->
<div class="settings-section" ng-if="Config.AUTHENTICATION_TYPE != 'AppToken'">
<h3>Docker CLI Password</h3>
<div ng-if="!Features.REQUIRE_ENCRYPTED_BASIC_AUTH">
The Docker CLI stores passwords entered on the command line in <strong>plaintext</strong>. It is therefore highly recommended to generate an an encrypted version of your password to use for <code>docker login</code>.
</div>
<div ng-if="Features.REQUIRE_ENCRYPTED_BASIC_AUTH">
This installation is set to <strong>require</strong> encrypted passwords when
using the Docker command line interface.
</div>
<table class="co-list-table" style="margin-top: 10px;">
<tr>
<td>CLI Password:</td>
<td>
<div ng-if="user.has_password_set">
<a ng-click="generateClientToken()">Generate Encrypted Password</a>
</div>
<div class="co-alert co-alert-info" ng-if="user.has_password_set === false">
A password must be set on your account before generating an encrypted version.
<span ng-show="!inReadOnlyMode">
Click <a ng-click="showChangePassword()">Set password</a> to set your password now.
</span>
</div>
</td>
</tr>
</table>
</div>
<!-- App Specific tokens -->
<div class="settings-section" ng-if="Features.APP_SPECIFIC_TOKENS">
<h3>Docker CLI and other Application Tokens</h3>
<div ng-if="Config.AUTHENTICATION_TYPE != 'AppToken'">
As an alternative to using your password for Docker and rkt CLIs, an application token can be generated below.
</div>
<div ng-if="Config.AUTHENTICATION_TYPE == 'AppToken'">
An application token is <strong>required</strong> to login via the Docker or rkt CLIs.
</div>
<app-specific-token-manager></app-specific-token-manager>
</div>
<!-- User Settings -->
<div class="settings-section" ng-show="!inReadOnlyMode">
<h3>User Settings</h3>
<table class="co-list-table">
<tr>
<td>Username:</td>
<td>
{{ context.viewuser.username }}
<div class="help-text">Usernames cannot currently be changed. Please <a href="/contact">contact support</a> to migrate accounts.</div>
</td>
</tr>
<tr>
<td>Avatar:</td>
<td>
<span class="avatar" size="48" data="context.viewuser.avatar"></span>
<div class="help-text" ng-if="Config.AVATAR_KIND == 'local'">Avatar is generated based off of your username.</div>
<div class="help-text" ng-if="Config.AVATAR_KIND == 'gravatar'">Avatar is served by <a href="http://gravatar.com" rel="nofollow" target="_blank">Gravatar</a> based on the {{ context.viewuser.email }} e-mail address.</div>
</td>
</tr>
<tr quay-show="Features.MAILING">
<td>Email Address:</td>
<td>
<div ng-if="context.emailAwaitingChange">
An email has been sent to <code>{{ context.emailAwaitingChange }}</code>. Please click the Confirm button
to apply the email change.
</div>
<a class="co-modify-link" ng-click="showChangeEmail()" ng-if="!context.emailAwaitingChange">{{ context.viewuser.email }}</a>
</td>
</tr>
<tr quay-show="Features.USER_METADATA">
<td>Given Name:</td>
<td>
<a class="co-modify-link" ng-click="showChangeMetadata('given_name', 'given name')">{{ context.viewuser.given_name || '(None)' }}</a>
</td>
</tr>
<tr quay-show="Features.USER_METADATA">
<td>Family Name:</td>
<td>
<a class="co-modify-link" ng-click="showChangeMetadata('family_name', 'family name')">{{ context.viewuser.family_name || '(None)' }}</a>
</td>
</tr>
<tr quay-show="Features.USER_METADATA">
<td>Company:</td>
<td>
<a class="co-modify-link" ng-click="showChangeMetadata('company', 'company name')">{{ context.viewuser.company || '(None)' }}</a>
</td>
</tr>
<tr quay-show="Features.USER_METADATA">
<td>Location:</td>
<td>
<a class="co-modify-link" ng-click="showChangeMetadata('location', 'location')">{{ context.viewuser.location || '(None)' }}</a>
</td>
</tr>
<tr quay-show="Config.AUTHENTICATION_TYPE == 'Database'">
<td>Password:</td>
<td>
<a class="co-modify-link" ng-click="showChangePassword()"><span ng-if="user.has_password_set">Change</span><span ng-if="!user.has_password_set">Set</span> password</a>
</td>
</tr>
<tr quay-show="Config.AUTHENTICATION_TYPE == 'Database'">
<td>Account Type:</td>
<td>
<a class="co-modify-link" ng-click="showChangeAccount()">Individual account</a>
</td>
</tr>
<tr>
<td>Desktop Notifications:</td>
<td>
<a class="co-modify-link"
ng-if="!desktopNotificationsPermissionIsDisabled()"
ng-disabled="desktopNotificationsPermissionIsDisabled()"
ng-click="toggleDesktopNotifications()"
ng-model="notificationsPermissionsEnabled"
>{{ notificationsPermissionsEnabled ? 'Enabled' : 'Disabled' }}
</a>
<span class="help-text"
ng-if="desktopNotificationsPermissionIsDisabled()">
Desktop notifications have been disabled, or are unavailable, in your browser.
</span>
</td>
</tr>
</table>
</div>
<div ng-show="!inReadOnlyMode">
<div class="delete-namespace-view" subscription-status="subscriptionStatus" user="context.viewuser" namespace-title="account" quay-show="Config.AUTHENTICATION_TYPE == 'Database'"></div>
<time-machine-settings user="context.viewuser"></time-machine-settings>
</div>
<!-- Billing Information -->
<div class="settings-section" quay-show="Features.BILLING" ng-show="!inReadOnlyMode">
<h3>Billing Information</h3>
<div class="billing-management-panel" user="context.viewuser" is-enabled="showBillingCounter" subscription-status="subscriptionStatus"></div>
</div>
</cor-tab-pane>
</cor-tab-content>
</cor-tab-panel>
<!-- Change metadata dialog -->
<div class="cor-confirm-dialog"
dialog-context="changeMetadataInfo"
dialog-action="updateMetadataInfo(info, callback)"
dialog-title="Update user information"
dialog-action-title="Update"
dialog-form="context.metadataform">
<form name="context.metadataform" class="co-single-field-dialog">
Please enter an updated {{ changeMetadataInfo.title }}:
<input type="text" class="form-control" ng-model="changeMetadataInfo.value">
</form>
</div>
<!-- Change email dialog -->
<div class="cor-confirm-dialog"
dialog-context="changeEmailInfo"
dialog-action="changeEmail(info, callback)"
dialog-title="Change E-mail Address"
dialog-action-title="Change Email"
dialog-form="context.emailform">
<form name="context.emailform" class="co-single-field-dialog">
Please enter a new email address. A verification email will be sent before the change is applied.
<input type="email" class="form-control" placeholder="Your new e-mail address"
ng-model="changeEmailInfo.email" required>
</form>
</div>
<!-- Change password dialog -->
<div class="cor-confirm-dialog"
dialog-context="changePasswordInfo"
dialog-action="changePassword(info, callback)"
dialog-title="Change Password"
dialog-action-title="Change Password"
dialog-form="context.passwordform">
<form name="context.passwordform" class="co-single-field-dialog">
Enter a new password. Passwords must be at least 8 characters in length.
<input type="password" class="form-control" placeholder="Your new password" ng-model="changePasswordInfo.password" required
ng-pattern="/^.{8,}$/">
<input type="password" class="form-control" placeholder="Verify your new password" ng-model="changePasswordInfo.repeatPassword"
match="changePasswordInfo.password" required ng-pattern="/^.{8,}$/">
</form>
</div>
<!-- Convert account dialog -->
<div class="convert-user-to-org" info="convertAccountInfo"></div>
<!-- Credentials for encrypted passwords -->
<div class="credentials-dialog" credentials="context.encryptedPasswordCredentials" secret-title="Encrypted Password" entity-title="encrypted password" entity-icon="fa-key"></div>
<!-- Credentials for ID token -->
<div class="credentials-dialog" credentials="context.idTokenCredentials" secret-title="CLI Token" entity-title="Docker CLI token" entity-icon="fa-key"></div>
</div>

View file

@ -0,0 +1,20 @@
<div class="cor-container">
<div ng-show="!user.anonymous && user.verified">
<h3>Welcome <b>{{ user.username }}</b>. Your account is fully activated!</h3>
<div style="margin-top: 20px;">
<a class="btn btn-lg btn-primary" href="/repository/">Browse all repositories</a>
</div>
</div>
<div ng-show="!user.anonymous && !user.verified">
<h3>Welcome <b>{{ user.username }}</b>. Your account is pending email confirmation.</h3>
<p>Please check your inbox (and potentially your spam folder) for an email from <a href="mailto:support@quay.io">support@quay.io</a></p>
</div>
<div ng-show="user.anonymous">
<h3>Docker sent me here. What do I need to do?</h3>
<p>
<a href="/signin">Sign In</a> to check the activation status of your account. If you have already activated
your account previously, then you do not need to do anything further.
</p>
</div>
</div>