Add tracking of the kind of temporary access tokens, so we can display if a pull/push by token is for a build worker

This commit is contained in:
Joseph Schorr 2015-02-17 12:35:16 -05:00
parent 3e04e3cfd7
commit 83e05d2342
10 changed files with 88 additions and 14 deletions

View file

@ -333,6 +333,10 @@ class PermissionPrototype(BaseModel):
)
class AccessTokenKind(BaseModel):
name = CharField(unique=True, index=True)
class AccessToken(BaseModel):
friendly_name = CharField(null=True)
code = CharField(default=random_string_generator(length=64), unique=True,
@ -341,6 +345,7 @@ class AccessToken(BaseModel):
created = DateTimeField(default=datetime.now)
role = ForeignKeyField(Role)
temporary = BooleanField(default=True)
kind = ForeignKeyField(AccessTokenKind, null=True)
class BuildTriggerService(BaseModel):
@ -600,4 +605,5 @@ all_models = [User, Repository, Image, AccessToken, Role, RepositoryPermission,
Notification, ImageStorageLocation, ImageStoragePlacement,
ExternalNotificationEvent, ExternalNotificationMethod, RepositoryNotification,
RepositoryAuthorizedEmail, ImageStorageTransformation, DerivedImageStorage,
TeamMemberInvite, ImageStorageSignature, ImageStorageSignatureKind]
TeamMemberInvite, ImageStorageSignature, ImageStorageSignatureKind,
AccessTokenKind]

View file

@ -0,0 +1,44 @@
"""Add access token kinds type
Revision ID: 3e2d38b52a75
Revises: 1d2d86d09fcd
Create Date: 2015-02-17 12:03:26.422485
"""
# revision identifiers, used by Alembic.
revision = '3e2d38b52a75'
down_revision = '1d2d86d09fcd'
from alembic import op
import sqlalchemy as sa
def upgrade(tables):
### commands auto generated by Alembic - please adjust! ###
op.create_table('accesstokenkind',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_accesstokenkind'))
)
op.create_index('accesstokenkind_name', 'accesstokenkind', ['name'], unique=True)
op.add_column(u'accesstoken', sa.Column('kind_id', sa.Integer(), nullable=True))
op.create_index('accesstoken_kind_id', 'accesstoken', ['kind_id'], unique=False)
op.create_foreign_key(op.f('fk_accesstoken_kind_id_accesstokenkind'), 'accesstoken', 'accesstokenkind', ['kind_id'], ['id'])
### end Alembic commands ###
op.bulk_insert(tables.accesstokenkind,
[
{'id': 1, 'name':'build-worker'},
{'id': 2, 'name':'pushpull-token'},
])
def downgrade(tables):
### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(op.f('fk_accesstoken_kind_id_accesstokenkind'), 'accesstoken', type_='foreignkey')
op.drop_index('accesstoken_kind_id', table_name='accesstoken')
op.drop_column(u'accesstoken', 'kind_id')
op.drop_index('accesstokenkind_name', table_name='accesstokenkind')
op.drop_table('accesstokenkind')
### end Alembic commands ###

View file

@ -15,7 +15,8 @@ from data.database import (User, Repository, Image, AccessToken, Role, Repositor
RepositoryNotification, RepositoryAuthorizedEmail, TeamMemberInvite,
DerivedImageStorage, ImageStorageTransformation, random_string_generator,
db, BUILD_PHASE, QuayUserField, ImageStorageSignature, QueueItem,
ImageStorageSignatureKind, validate_database_url, db_for_update)
ImageStorageSignatureKind, validate_database_url, db_for_update,
AccessTokenKind)
from peewee import JOIN_LEFT_OUTER, fn
from util.validation import (validate_username, validate_email, validate_password,
INVALID_PASSWORD_MESSAGE)
@ -1902,10 +1903,14 @@ def get_private_repo_count(username):
.count())
def create_access_token(repository, role):
def create_access_token(repository, role, kind=None, friendly_name=None):
role = Role.get(Role.name == role)
kind_ref = None
if kind is not None:
kind_ref = AccessTokenKind.get(AccessTokenKind.name == kind)
new_token = AccessToken.create(repository=repository, temporary=True,
role=role)
role=role, kind=kind_ref, friendly_name=friendly_name)
return new_token

View file

@ -215,7 +215,8 @@ def start_build(repository, dockerfile_id, tags, build_name, subdir, manual,
host = urlparse.urlparse(request.url).netloc
repo_path = '%s/%s/%s' % (host, repository.namespace_user.username, repository.name)
token = model.create_access_token(repository, 'write')
token = model.create_access_token(repository, 'write', kind='build-worker',
friendly_name='Repository Build Token')
logger.debug('Creating build %s with repo %s tags %s and dockerfile_id %s',
build_name, repo_path, tags, dockerfile_id)

View file

@ -50,7 +50,7 @@ def generate_headers(role='read'):
if has_token_request:
repo = model.get_repository(namespace, repository)
if repo:
token = model.create_access_token(repo, role)
token = model.create_access_token(repo, role, 'pushpull-token')
token_str = 'signature=%s' % token.code
response.headers['WWW-Authenticate'] = token_str
response.headers['X-Docker-Token'] = token_str

View file

@ -34,6 +34,10 @@ def track_and_log(event_name, repo, **kwargs):
elif authenticated_token:
metadata['token'] = authenticated_token.friendly_name
metadata['token_code'] = authenticated_token.code
if authenticated_token.kind:
metadata['token_type'] = authenticated_token.kind.name
analytics_id = 'token:' + authenticated_token.code
else:
metadata['public'] = True

View file

@ -192,6 +192,9 @@ def initialize_database():
BuildTriggerService.create(name='github')
AccessTokenKind.create(name='build-worker')
AccessTokenKind.create(name='pushpull-token')
LogEntryKind.create(name='account_change_plan')
LogEntryKind.create(name='account_change_cc')
LogEntryKind.create(name='account_change_password')
@ -393,7 +396,7 @@ def populate_database():
'Empty repository which is building.',
False, [], (0, [], None))
token = model.create_access_token(building, 'write')
token = model.create_access_token(building, 'write', 'build-worker')
trigger = model.create_build_trigger(building, 'github', '123authtoken',
new_user_1, pull_robot=dtrobot[0])

View file

@ -56,7 +56,8 @@
<td>
<span class="log-performer" ng-if="log.metadata.oauth_token_application">
<div>
<span class="application-reference" data-title="log.metadata.oauth_token_application"
<span class="application-reference"
data-title="log.metadata.oauth_token_application"
client-id="log.metadata.oauth_token_application_id"></span>
</div>
<div style="text-align: center; font-size: 12px; color: #aaa; padding: 4px;">on behalf of</div>

View file

@ -3314,7 +3314,11 @@ quayApp.directive('logsView', function () {
}
if (metadata.token) {
prefix += ' via token {token}';
if (metadata.token_type == 'build-worker') {
prefix += ' by <b>build worker</b>';
} else {
prefix += ' via token';
}
} else if (metadata.username) {
prefix += ' by {username}';
} else {
@ -3325,7 +3329,13 @@ quayApp.directive('logsView', function () {
},
'pull_repo': function(metadata) {
if (metadata.token) {
return 'Pull repository {repo} via token {token}';
var prefix = 'Pull of repository'
if (metadata.token_type == 'build-worker') {
prefix += ' by <b>build worker</b>';
} else {
prefix += ' via token';
}
return prefix;
} else if (metadata.username) {
return 'Pull repository {repo} by {username}';
} else {

Binary file not shown.