2013-09-20 15:55:44 +00:00
|
|
|
import string
|
2013-10-02 16:43:45 +00:00
|
|
|
import logging
|
2014-02-04 00:08:37 +00:00
|
|
|
import uuid
|
2013-09-20 15:55:44 +00:00
|
|
|
|
2013-09-30 23:10:27 +00:00
|
|
|
from random import SystemRandom
|
|
|
|
from datetime import datetime
|
2013-09-20 15:55:44 +00:00
|
|
|
from peewee import *
|
2014-07-02 23:10:24 +00:00
|
|
|
from data.read_slave import ReadSlaveModel
|
2014-04-10 22:30:09 +00:00
|
|
|
from sqlalchemy.engine.url import make_url
|
2014-04-09 23:11:33 +00:00
|
|
|
from urlparse import urlparse
|
2014-09-11 19:45:41 +00:00
|
|
|
from util.names import urn_generator
|
2013-09-20 15:55:44 +00:00
|
|
|
|
2013-10-02 16:43:45 +00:00
|
|
|
logger = logging.getLogger(__name__)
|
2014-04-07 20:59:22 +00:00
|
|
|
|
2014-04-09 23:11:33 +00:00
|
|
|
|
|
|
|
SCHEME_DRIVERS = {
|
2014-05-19 21:14:23 +00:00
|
|
|
'mysql': MySQLDatabase,
|
2014-05-22 16:13:41 +00:00
|
|
|
'mysql+pymysql': MySQLDatabase,
|
2014-04-09 23:11:33 +00:00
|
|
|
'sqlite': SqliteDatabase,
|
2014-08-21 23:21:20 +00:00
|
|
|
'postgresql': PostgresqlDatabase,
|
|
|
|
'postgresql+psycopg2': PostgresqlDatabase,
|
2014-04-07 20:59:22 +00:00
|
|
|
}
|
|
|
|
|
2014-09-15 19:58:56 +00:00
|
|
|
SCHEME_RANDOM_FUNCTION = {
|
|
|
|
'mysql': fn.Rand,
|
|
|
|
'mysql+pymysql': fn.Rand,
|
|
|
|
'sqlite': fn.Random,
|
|
|
|
'postgresql': fn.Random,
|
|
|
|
'postgresql+psycopg2': fn.Random,
|
|
|
|
}
|
|
|
|
|
|
|
|
class CallableProxy(Proxy):
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
|
|
if self.obj is None:
|
|
|
|
raise AttributeError('Cannot use uninitialized Proxy.')
|
|
|
|
return self.obj(*args, **kwargs)
|
|
|
|
|
2014-05-13 16:17:26 +00:00
|
|
|
db = Proxy()
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slave = Proxy()
|
2014-09-15 19:58:56 +00:00
|
|
|
db_random_func = CallableProxy()
|
|
|
|
|
2014-04-09 23:11:33 +00:00
|
|
|
|
2014-07-02 23:10:24 +00:00
|
|
|
def _db_from_url(url, db_kwargs):
|
|
|
|
parsed_url = make_url(url)
|
2014-04-10 22:30:09 +00:00
|
|
|
|
|
|
|
if parsed_url.host:
|
|
|
|
db_kwargs['host'] = parsed_url.host
|
|
|
|
if parsed_url.port:
|
|
|
|
db_kwargs['port'] = parsed_url.port
|
|
|
|
if parsed_url.username:
|
|
|
|
db_kwargs['user'] = parsed_url.username
|
|
|
|
if parsed_url.password:
|
2014-08-21 23:21:20 +00:00
|
|
|
db_kwargs['password'] = parsed_url.password
|
2014-04-10 22:30:09 +00:00
|
|
|
|
2014-07-02 23:10:24 +00:00
|
|
|
return SCHEME_DRIVERS[parsed_url.drivername](parsed_url.database, **db_kwargs)
|
|
|
|
|
2014-09-15 19:58:56 +00:00
|
|
|
|
2014-07-02 23:10:24 +00:00
|
|
|
def configure(config_object):
|
|
|
|
db_kwargs = dict(config_object['DB_CONNECTION_ARGS'])
|
|
|
|
write_db_uri = config_object['DB_URI']
|
|
|
|
db.initialize(_db_from_url(write_db_uri, db_kwargs))
|
|
|
|
|
2014-09-15 19:58:56 +00:00
|
|
|
parsed_write_uri = make_url(write_db_uri)
|
|
|
|
db_random_func.initialize(SCHEME_RANDOM_FUNCTION[parsed_write_uri.drivername])
|
|
|
|
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slave_uri = config_object.get('DB_READ_SLAVE_URI', None)
|
|
|
|
if read_slave_uri is not None:
|
|
|
|
read_slave.initialize(_db_from_url(read_slave_uri, db_kwargs))
|
2014-04-09 23:11:33 +00:00
|
|
|
|
2013-09-20 15:55:44 +00:00
|
|
|
|
2013-11-20 21:13:03 +00:00
|
|
|
def random_string_generator(length=16):
|
|
|
|
def random_string():
|
|
|
|
random = SystemRandom()
|
|
|
|
return ''.join([random.choice(string.ascii_uppercase + string.digits)
|
|
|
|
for _ in range(length)])
|
|
|
|
return random_string
|
|
|
|
|
|
|
|
|
2014-02-04 00:08:37 +00:00
|
|
|
def uuid_generator():
|
|
|
|
return str(uuid.uuid4())
|
|
|
|
|
|
|
|
|
2014-07-02 23:10:24 +00:00
|
|
|
class BaseModel(ReadSlaveModel):
|
2013-09-20 15:55:44 +00:00
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2013-09-20 15:55:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
class User(BaseModel):
|
2013-09-28 03:33:59 +00:00
|
|
|
username = CharField(unique=True, index=True)
|
2013-10-10 03:00:34 +00:00
|
|
|
password_hash = CharField(null=True)
|
2013-11-20 21:13:03 +00:00
|
|
|
email = CharField(unique=True, index=True,
|
|
|
|
default=random_string_generator(length=64))
|
2013-09-27 23:55:04 +00:00
|
|
|
verified = BooleanField(default=False)
|
2013-10-02 04:48:03 +00:00
|
|
|
stripe_id = CharField(index=True, null=True)
|
2013-10-31 20:46:04 +00:00
|
|
|
organization = BooleanField(default=False, index=True)
|
2013-11-20 21:13:03 +00:00
|
|
|
robot = BooleanField(default=False, index=True)
|
2013-11-15 19:42:31 +00:00
|
|
|
invoice_email = BooleanField(default=False)
|
2014-09-02 19:27:05 +00:00
|
|
|
invalid_login_attempts = IntegerField(default=0)
|
|
|
|
last_invalid_login = DateTimeField(default=datetime.utcnow)
|
2013-10-31 20:46:04 +00:00
|
|
|
|
|
|
|
|
2013-11-04 20:42:08 +00:00
|
|
|
class TeamRole(BaseModel):
|
|
|
|
name = CharField(index=True)
|
|
|
|
|
|
|
|
|
2013-10-31 20:46:04 +00:00
|
|
|
class Team(BaseModel):
|
2013-11-01 23:34:17 +00:00
|
|
|
name = CharField(index=True)
|
2013-10-31 20:46:04 +00:00
|
|
|
organization = ForeignKeyField(User, index=True)
|
2013-11-04 20:42:08 +00:00
|
|
|
role = ForeignKeyField(TeamRole)
|
2013-11-04 21:57:20 +00:00
|
|
|
description = TextField(default='')
|
2013-10-31 20:46:04 +00:00
|
|
|
|
2013-11-01 23:34:17 +00:00
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2013-11-01 23:34:17 +00:00
|
|
|
indexes = (
|
|
|
|
# A team name must be unique within an organization
|
|
|
|
(('name', 'organization'), True),
|
|
|
|
)
|
|
|
|
|
2013-10-31 20:46:04 +00:00
|
|
|
|
|
|
|
class TeamMember(BaseModel):
|
|
|
|
user = ForeignKeyField(User, index=True)
|
|
|
|
team = ForeignKeyField(Team, index=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2013-10-31 20:46:04 +00:00
|
|
|
indexes = (
|
|
|
|
# A user may belong to a team only once
|
|
|
|
(('user', 'team'), True),
|
|
|
|
)
|
2013-09-20 15:55:44 +00:00
|
|
|
|
|
|
|
|
2014-08-15 21:47:43 +00:00
|
|
|
class TeamMemberInvite(BaseModel):
|
|
|
|
# Note: Either user OR email will be filled in, but not both.
|
|
|
|
user = ForeignKeyField(User, index=True, null=True)
|
|
|
|
email = CharField(null=True)
|
|
|
|
team = ForeignKeyField(Team, index=True)
|
2014-08-18 21:24:00 +00:00
|
|
|
inviter = ForeignKeyField(User, related_name='inviter')
|
2014-09-11 19:45:41 +00:00
|
|
|
invite_token = CharField(default=urn_generator(['teaminvite']))
|
2014-08-15 21:47:43 +00:00
|
|
|
|
|
|
|
|
2013-10-10 03:00:34 +00:00
|
|
|
class LoginService(BaseModel):
|
|
|
|
name = CharField(unique=True, index=True)
|
|
|
|
|
|
|
|
|
|
|
|
class FederatedLogin(BaseModel):
|
|
|
|
user = ForeignKeyField(User, index=True)
|
|
|
|
service = ForeignKeyField(LoginService, index=True)
|
|
|
|
service_ident = CharField()
|
2014-08-11 22:25:01 +00:00
|
|
|
metadata_json = TextField(default='{}')
|
2013-10-10 03:00:34 +00:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2013-10-10 03:00:34 +00:00
|
|
|
indexes = (
|
|
|
|
# create a unique index on service and the local service id
|
|
|
|
(('service', 'service_ident'), True),
|
|
|
|
|
|
|
|
# a user may only have one federated login per service
|
|
|
|
(('service', 'user'), True),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2013-09-20 22:38:17 +00:00
|
|
|
class Visibility(BaseModel):
|
2014-05-29 15:24:10 +00:00
|
|
|
name = CharField(index=True, unique=True)
|
2013-09-20 22:38:17 +00:00
|
|
|
|
|
|
|
|
2013-09-20 15:55:44 +00:00
|
|
|
class Repository(BaseModel):
|
|
|
|
namespace = CharField()
|
2014-09-18 18:52:29 +00:00
|
|
|
namespace_user = ForeignKeyField(User, null=True)
|
2013-09-20 15:55:44 +00:00
|
|
|
name = CharField()
|
2013-09-20 22:38:17 +00:00
|
|
|
visibility = ForeignKeyField(Visibility)
|
2013-10-01 03:22:52 +00:00
|
|
|
description = TextField(null=True)
|
2014-02-28 21:23:36 +00:00
|
|
|
badge_token = CharField(default=uuid_generator)
|
2013-09-20 15:55:44 +00:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2013-09-20 15:55:44 +00:00
|
|
|
indexes = (
|
|
|
|
# create a unique index on namespace and name
|
|
|
|
(('namespace', 'name'), True),
|
2014-09-22 21:27:02 +00:00
|
|
|
(('namespace_user', 'name'), False),
|
2013-09-20 15:55:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2013-09-20 22:38:17 +00:00
|
|
|
class Role(BaseModel):
|
2014-05-29 15:24:10 +00:00
|
|
|
name = CharField(index=True, unique=True)
|
2013-09-20 22:38:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
class RepositoryPermission(BaseModel):
|
2013-11-01 23:34:17 +00:00
|
|
|
team = ForeignKeyField(Team, index=True, null=True)
|
|
|
|
user = ForeignKeyField(User, index=True, null=True)
|
2013-09-28 03:33:59 +00:00
|
|
|
repository = ForeignKeyField(Repository, index=True)
|
2013-09-20 22:38:17 +00:00
|
|
|
role = ForeignKeyField(Role)
|
|
|
|
|
2013-09-28 03:33:59 +00:00
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2013-09-28 03:33:59 +00:00
|
|
|
indexes = (
|
2013-11-01 23:34:17 +00:00
|
|
|
(('team', 'repository'), True),
|
2013-09-28 03:33:59 +00:00
|
|
|
(('user', 'repository'), True),
|
|
|
|
)
|
|
|
|
|
2013-09-20 22:38:17 +00:00
|
|
|
|
2014-01-17 22:28:21 +00:00
|
|
|
class PermissionPrototype(BaseModel):
|
2014-01-20 22:39:29 +00:00
|
|
|
org = ForeignKeyField(User, index=True, related_name='orgpermissionproto')
|
2014-02-04 00:08:37 +00:00
|
|
|
uuid = CharField(default=uuid_generator)
|
2014-01-21 00:05:26 +00:00
|
|
|
activating_user = ForeignKeyField(User, index=True, null=True,
|
|
|
|
related_name='userpermissionproto')
|
|
|
|
delegate_user = ForeignKeyField(User, related_name='receivingpermission',
|
|
|
|
null=True)
|
|
|
|
delegate_team = ForeignKeyField(Team, related_name='receivingpermission',
|
|
|
|
null=True)
|
2014-01-17 22:28:21 +00:00
|
|
|
role = ForeignKeyField(Role)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2014-01-17 22:28:21 +00:00
|
|
|
indexes = (
|
2014-01-21 00:05:26 +00:00
|
|
|
(('org', 'activating_user'), False),
|
2014-01-17 22:28:21 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2013-11-15 21:45:02 +00:00
|
|
|
|
2013-09-20 15:55:44 +00:00
|
|
|
class AccessToken(BaseModel):
|
2013-10-16 18:24:10 +00:00
|
|
|
friendly_name = CharField(null=True)
|
|
|
|
code = CharField(default=random_string_generator(length=64), unique=True,
|
|
|
|
index=True)
|
2013-09-20 15:55:44 +00:00
|
|
|
repository = ForeignKeyField(Repository)
|
|
|
|
created = DateTimeField(default=datetime.now)
|
2013-10-16 18:24:10 +00:00
|
|
|
role = ForeignKeyField(Role)
|
|
|
|
temporary = BooleanField(default=True)
|
2013-09-20 15:55:44 +00:00
|
|
|
|
|
|
|
|
2014-02-21 22:09:56 +00:00
|
|
|
class BuildTriggerService(BaseModel):
|
2014-05-29 15:24:10 +00:00
|
|
|
name = CharField(index=True, unique=True)
|
2014-02-21 22:09:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
class RepositoryBuildTrigger(BaseModel):
|
|
|
|
uuid = CharField(default=uuid_generator)
|
|
|
|
service = ForeignKeyField(BuildTriggerService, index=True)
|
|
|
|
repository = ForeignKeyField(Repository, index=True)
|
|
|
|
connected_user = ForeignKeyField(User)
|
|
|
|
auth_token = CharField()
|
|
|
|
config = TextField(default='{}')
|
|
|
|
write_token = ForeignKeyField(AccessToken, null=True)
|
2014-04-02 01:49:06 +00:00
|
|
|
pull_robot = ForeignKeyField(User, null=True, related_name='triggerpullrobot')
|
2014-02-21 22:09:56 +00:00
|
|
|
|
|
|
|
|
2013-09-27 23:29:01 +00:00
|
|
|
class EmailConfirmation(BaseModel):
|
2013-09-28 03:33:59 +00:00
|
|
|
code = CharField(default=random_string_generator(), unique=True, index=True)
|
2013-09-27 23:29:01 +00:00
|
|
|
user = ForeignKeyField(User)
|
|
|
|
pw_reset = BooleanField(default=False)
|
2014-01-17 22:09:31 +00:00
|
|
|
new_email = CharField(null=True)
|
2013-09-27 23:29:01 +00:00
|
|
|
email_confirm = BooleanField(default=False)
|
|
|
|
created = DateTimeField(default=datetime.now)
|
|
|
|
|
|
|
|
|
2014-02-16 22:38:47 +00:00
|
|
|
class ImageStorage(BaseModel):
|
|
|
|
uuid = CharField(default=uuid_generator)
|
|
|
|
checksum = CharField(null=True)
|
|
|
|
created = DateTimeField(null=True)
|
|
|
|
comment = TextField(null=True)
|
|
|
|
command = TextField(null=True)
|
2014-05-02 20:59:46 +00:00
|
|
|
image_size = BigIntegerField(null=True)
|
2014-09-23 18:01:27 +00:00
|
|
|
uncompressed_size = BigIntegerField(null=True)
|
2014-05-02 20:59:46 +00:00
|
|
|
uploading = BooleanField(default=True, null=True)
|
2014-02-16 22:38:47 +00:00
|
|
|
|
|
|
|
|
2014-06-17 20:03:43 +00:00
|
|
|
class ImageStorageLocation(BaseModel):
|
|
|
|
name = CharField(unique=True, index=True)
|
|
|
|
|
|
|
|
|
|
|
|
class ImageStoragePlacement(BaseModel):
|
|
|
|
storage = ForeignKeyField(ImageStorage)
|
|
|
|
location = ForeignKeyField(ImageStorageLocation)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2014-06-17 20:03:43 +00:00
|
|
|
indexes = (
|
|
|
|
# An image can only be placed in the same place once
|
|
|
|
(('storage', 'location'), True),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2013-09-20 15:55:44 +00:00
|
|
|
class Image(BaseModel):
|
2013-09-26 19:58:11 +00:00
|
|
|
# This class is intentionally denormalized. Even though images are supposed
|
|
|
|
# to be globally unique we can't treat them as such for permissions and
|
|
|
|
# security reasons. So rather than Repository <-> Image being many to many
|
|
|
|
# each image now belongs to exactly one repository.
|
2013-10-01 18:14:39 +00:00
|
|
|
docker_image_id = CharField()
|
2013-09-25 20:46:28 +00:00
|
|
|
repository = ForeignKeyField(Repository)
|
|
|
|
|
2013-09-30 19:30:00 +00:00
|
|
|
# '/' separated list of ancestory ids, e.g. /1/2/6/7/10/
|
2014-02-14 21:06:30 +00:00
|
|
|
ancestors = CharField(index=True, default='/', max_length=64535, null=True)
|
|
|
|
|
|
|
|
storage = ForeignKeyField(ImageStorage, index=True, null=True)
|
2013-09-30 19:30:00 +00:00
|
|
|
|
2013-09-20 15:55:44 +00:00
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2013-09-20 15:55:44 +00:00
|
|
|
indexes = (
|
|
|
|
# we don't really want duplicates
|
2014-06-11 19:37:45 +00:00
|
|
|
(('repository', 'docker_image_id'), True),
|
2013-09-20 15:55:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
2013-09-26 19:58:11 +00:00
|
|
|
class RepositoryTag(BaseModel):
|
|
|
|
name = CharField()
|
|
|
|
image = ForeignKeyField(Image)
|
|
|
|
repository = ForeignKeyField(Repository)
|
|
|
|
|
2013-09-28 03:33:59 +00:00
|
|
|
class Meta:
|
|
|
|
database = db
|
2014-07-02 23:10:24 +00:00
|
|
|
read_slaves = (read_slave,)
|
2013-09-28 03:33:59 +00:00
|
|
|
indexes = (
|
|
|
|
(('repository', 'name'), True),
|
|
|
|
)
|
|
|
|
|
2013-09-26 19:58:11 +00:00
|
|
|
|
2014-09-08 20:43:17 +00:00
|
|
|
class BUILD_PHASE(object):
|
|
|
|
""" Build phases enum """
|
|
|
|
ERROR = 'error'
|
|
|
|
UNPACKING = 'unpacking'
|
|
|
|
PULLING = 'pulling'
|
|
|
|
BUILDING = 'building'
|
|
|
|
PUSHING = 'pushing'
|
|
|
|
COMPLETE = 'complete'
|
|
|
|
|
|
|
|
|
2013-10-24 20:37:03 +00:00
|
|
|
class RepositoryBuild(BaseModel):
|
2014-02-04 00:08:37 +00:00
|
|
|
uuid = CharField(default=uuid_generator, index=True)
|
|
|
|
repository = ForeignKeyField(Repository, index=True)
|
2013-10-25 22:17:43 +00:00
|
|
|
access_token = ForeignKeyField(AccessToken)
|
2014-02-25 23:22:02 +00:00
|
|
|
resource_key = CharField(index=True)
|
2014-02-24 21:11:23 +00:00
|
|
|
job_config = TextField()
|
2013-10-24 20:37:03 +00:00
|
|
|
phase = CharField(default='waiting')
|
2014-02-11 17:25:38 +00:00
|
|
|
started = DateTimeField(default=datetime.now)
|
2014-02-12 18:52:12 +00:00
|
|
|
display_name = CharField()
|
2014-02-19 21:08:33 +00:00
|
|
|
trigger = ForeignKeyField(RepositoryBuildTrigger, null=True, index=True)
|
2014-04-02 01:49:06 +00:00
|
|
|
pull_robot = ForeignKeyField(User, null=True, related_name='buildpullrobot')
|
2014-09-08 20:43:17 +00:00
|
|
|
logs_archived = BooleanField(default=False)
|
2013-10-24 20:37:03 +00:00
|
|
|
|
|
|
|
|
2013-10-18 18:30:49 +00:00
|
|
|
class QueueItem(BaseModel):
|
2014-04-11 22:34:47 +00:00
|
|
|
queue_name = CharField(index=True, max_length=1024)
|
2013-10-17 22:25:19 +00:00
|
|
|
body = TextField()
|
2014-09-22 16:52:57 +00:00
|
|
|
available_after = DateTimeField(default=datetime.utcnow, index=True)
|
2013-10-17 22:25:19 +00:00
|
|
|
available = BooleanField(default=True, index=True)
|
|
|
|
processing_expires = DateTimeField(null=True, index=True)
|
2013-11-15 20:49:26 +00:00
|
|
|
retries_remaining = IntegerField(default=5)
|
2013-10-17 22:25:19 +00:00
|
|
|
|
|
|
|
|
2013-11-27 07:29:31 +00:00
|
|
|
class LogEntryKind(BaseModel):
|
2014-05-29 15:24:10 +00:00
|
|
|
name = CharField(index=True, unique=True)
|
2013-11-27 07:29:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
class LogEntry(BaseModel):
|
|
|
|
kind = ForeignKeyField(LogEntryKind, index=True)
|
2013-12-02 23:15:59 +00:00
|
|
|
account = ForeignKeyField(User, index=True, related_name='account')
|
|
|
|
performer = ForeignKeyField(User, index=True, null=True,
|
|
|
|
related_name='performer')
|
2013-11-27 07:29:31 +00:00
|
|
|
repository = ForeignKeyField(Repository, index=True, null=True)
|
|
|
|
access_token = ForeignKeyField(AccessToken, null=True)
|
|
|
|
datetime = DateTimeField(default=datetime.now, index=True)
|
|
|
|
ip = CharField(null=True)
|
|
|
|
metadata_json = TextField(default='{}')
|
|
|
|
|
|
|
|
|
2014-03-12 16:37:06 +00:00
|
|
|
class OAuthApplication(BaseModel):
|
|
|
|
client_id = CharField(index=True, default=random_string_generator(length=20))
|
|
|
|
client_secret = CharField(default=random_string_generator(length=40))
|
|
|
|
redirect_uri = CharField()
|
2014-03-14 22:57:28 +00:00
|
|
|
application_uri = CharField()
|
2014-03-12 16:37:06 +00:00
|
|
|
organization = ForeignKeyField(User)
|
2014-03-20 19:46:13 +00:00
|
|
|
|
2014-03-14 22:57:28 +00:00
|
|
|
name = CharField()
|
|
|
|
description = TextField(default='')
|
2014-03-20 19:46:13 +00:00
|
|
|
gravatar_email = CharField(null=True)
|
2014-03-12 16:37:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
class OAuthAuthorizationCode(BaseModel):
|
|
|
|
application = ForeignKeyField(OAuthApplication)
|
|
|
|
code = CharField(index=True)
|
|
|
|
scope = CharField()
|
2014-03-25 20:06:34 +00:00
|
|
|
data = TextField() # Context for the code, such as the user
|
2014-03-12 16:37:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
class OAuthAccessToken(BaseModel):
|
2014-03-25 00:57:02 +00:00
|
|
|
uuid = CharField(default=uuid_generator, index=True)
|
2014-03-12 16:37:06 +00:00
|
|
|
application = ForeignKeyField(OAuthApplication)
|
|
|
|
authorized_user = ForeignKeyField(User)
|
|
|
|
scope = CharField()
|
|
|
|
access_token = CharField(index=True)
|
|
|
|
token_type = CharField(default='Bearer')
|
|
|
|
expires_at = DateTimeField()
|
|
|
|
refresh_token = CharField(index=True, null=True)
|
2014-03-25 16:42:40 +00:00
|
|
|
data = TextField() # This is context for which this token was generated, such as the user
|
2014-03-12 16:37:06 +00:00
|
|
|
|
|
|
|
|
2014-03-12 04:49:03 +00:00
|
|
|
class NotificationKind(BaseModel):
|
2014-05-29 15:24:10 +00:00
|
|
|
name = CharField(index=True, unique=True)
|
2014-03-12 04:49:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Notification(BaseModel):
|
|
|
|
uuid = CharField(default=uuid_generator, index=True)
|
|
|
|
kind = ForeignKeyField(NotificationKind, index=True)
|
2014-03-12 23:00:24 +00:00
|
|
|
target = ForeignKeyField(User, index=True)
|
2014-03-12 04:49:03 +00:00
|
|
|
metadata_json = TextField(default='{}')
|
|
|
|
created = DateTimeField(default=datetime.now, index=True)
|
2014-07-28 22:23:46 +00:00
|
|
|
dismissed = BooleanField(default=False)
|
2014-03-12 04:49:03 +00:00
|
|
|
|
2014-07-16 20:30:47 +00:00
|
|
|
|
|
|
|
class ExternalNotificationEvent(BaseModel):
|
|
|
|
name = CharField(index=True, unique=True)
|
|
|
|
|
|
|
|
|
|
|
|
class ExternalNotificationMethod(BaseModel):
|
|
|
|
name = CharField(index=True, unique=True)
|
|
|
|
|
|
|
|
|
|
|
|
class RepositoryNotification(BaseModel):
|
|
|
|
uuid = CharField(default=uuid_generator, index=True)
|
|
|
|
repository = ForeignKeyField(Repository, index=True)
|
|
|
|
event = ForeignKeyField(ExternalNotificationEvent)
|
|
|
|
method = ForeignKeyField(ExternalNotificationMethod)
|
|
|
|
config_json = TextField()
|
|
|
|
|
|
|
|
|
2014-07-28 18:58:12 +00:00
|
|
|
class RepositoryAuthorizedEmail(BaseModel):
|
|
|
|
repository = ForeignKeyField(Repository, index=True)
|
|
|
|
email = CharField()
|
|
|
|
code = CharField(default=random_string_generator(), unique=True, index=True)
|
|
|
|
confirmed = BooleanField(default=False)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
database = db
|
|
|
|
read_slaves = (read_slave,)
|
|
|
|
indexes = (
|
|
|
|
# create a unique index on email and repository
|
|
|
|
(('email', 'repository'), True),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-03-12 16:37:06 +00:00
|
|
|
all_models = [User, Repository, Image, AccessToken, Role, RepositoryPermission, Visibility,
|
|
|
|
RepositoryTag, EmailConfirmation, FederatedLogin, LoginService, QueueItem,
|
2014-07-16 20:30:47 +00:00
|
|
|
RepositoryBuild, Team, TeamMember, TeamRole, LogEntryKind, LogEntry,
|
2014-03-12 16:37:06 +00:00
|
|
|
PermissionPrototype, ImageStorage, BuildTriggerService, RepositoryBuildTrigger,
|
2014-03-19 19:39:44 +00:00
|
|
|
OAuthApplication, OAuthAuthorizationCode, OAuthAccessToken, NotificationKind,
|
2014-07-16 20:30:47 +00:00
|
|
|
Notification, ImageStorageLocation, ImageStoragePlacement,
|
2014-07-28 18:58:12 +00:00
|
|
|
ExternalNotificationEvent, ExternalNotificationMethod, RepositoryNotification,
|
2014-08-15 21:47:43 +00:00
|
|
|
RepositoryAuthorizedEmail, TeamMemberInvite]
|