Use account_id to identify the user's own account

This is necessary on systems where the username may not be present
(e.g., gerrit-review.googlesource.com).

Change-Id: Ia91b1e9b0fb0f98728dca46a488a92a97a301274
This commit is contained in:
James E. Blair 2019-08-28 15:06:15 +02:00
parent 87d0f36c50
commit 73a6481835
8 changed files with 101 additions and 22 deletions

View File

@ -0,0 +1,26 @@
"""add_server_table
Revision ID: a18731009699
Revises: 399c4b3dcc9a
Create Date: 2019-08-28 14:12:22.657691
"""
# revision identifiers, used by Alembic.
revision = 'a18731009699'
down_revision = '399c4b3dcc9a'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.create_table('server',
sa.Column('key', sa.Integer(), nullable=False),
sa.Column('own_account_key', sa.Integer(), sa.ForeignKey('own_account.key'), index=True),
sa.PrimaryKeyConstraint('key')
)
def downgrade():
pass

View File

@ -289,8 +289,15 @@ class App(object):
self.fetch_missing_refs = fetch_missing_refs
self.config.keymap.updateCommandMap()
self.search = search.SearchCompiler(self.config.username)
self.search = search.SearchCompiler(self.getOwnAccountId)
self.db = db.Database(self, self.config.dburi, self.search)
self.own_account_id = None
with self.db.getSession() as session:
account = session.getOwnAccount()
if account:
self.own_account_id = account.id
self.sync = sync.Sync(self, disable_background_sync)
self.status = StatusHeader(self)
@ -342,6 +349,12 @@ class App(object):
self.sync.offline = True
self.status.update(offline=True)
def getOwnAccountId(self):
return self.own_account_id
def isOwnAccount(self, account):
return account.id == self.own_account_id
def run(self):
try:
self.loop.run()
@ -801,8 +814,7 @@ class App(object):
def saveReviews(self, revision_keys, approvals, message, upload, submit):
message_keys = []
with self.db.getSession() as session:
account = session.getAccountByUsername(self.config.username)
account = session.getAccountByID(self.sync.account_id)
account = session.getOwnAccount()
for revision_key in revision_keys:
k = self._saveReview(session, account, revision_key,
approvals, message, upload, submit)

View File

@ -192,6 +192,11 @@ file_table = Table(
Column('deleted', Integer),
Column('status', String(1), nullable=False),
)
server_table = Table(
'server', metadata,
Column('key', Integer, primary_key=True),
Column('own_account_key', Integer, ForeignKey("account.key"), index=True),
)
class Account(object):
@ -644,6 +649,10 @@ class File(object):
session.flush()
return c
class Server(object):
def __init__(self):
pass
mapper(Account, account_table)
mapper(Project, project_table, properties=dict(
@ -750,6 +759,9 @@ mapper(Approval, approval_table, properties=dict(
mapper(PendingCherryPick, pending_cherry_pick_table)
mapper(SyncQuery, sync_query_table)
mapper(Hashtag, hashtag_table)
mapper(Server, server_table, properties=dict(
own_account=relationship(Account)
))
def match(expr, item):
if item is None:
@ -763,6 +775,7 @@ def add_sqlite_match(dbapi_connection, connection_record):
class Database(object):
def __init__(self, app, dburi, search):
self.log = logging.getLogger('gertty.db')
self.own_account_key = None
self.dburi = dburi
self.search = search
self.engine = create_engine(self.dburi)
@ -1057,6 +1070,28 @@ class DatabaseSession(object):
def getSystemAccount(self):
return self.getAccountByID(0, 'Gerrit Code Review')
def setOwnAccount(self, account):
try:
server = self.session().query(Server).one()
except sqlalchemy.orm.exc.NoResultFound:
server = Server()
self.session().add(server)
self.session().flush()
server.own_account = account
self.database.own_account_key = account.key
def getOwnAccount(self):
if self.database.own_account_key is None:
try:
server = self.session().query(Server).one()
except sqlalchemy.orm.exc.NoResultFound:
return None
self.database.own_account_key = server.own_account.key
try:
return self.session().query(Account).filter_by(key=self.database.own_account_key).one()
except sqlalchemy.orm.exc.NoResultFound:
return None
def createProject(self, *args, **kw):
o = Project(*args, **kw)
self.session().add(o)

View File

@ -25,10 +25,11 @@ class SearchSyntaxError(Exception):
class SearchCompiler(object):
def __init__(self, username):
self.username = username
def __init__(self, get_account_id):
self.get_account_id = get_account_id
self.lexer = tokenizer.SearchTokenizer()
self.parser = parser.SearchParser()
self.parser.account_id = None
def findTables(self, expression):
tables = set()
@ -45,7 +46,10 @@ class SearchCompiler(object):
return tables
def parse(self, data):
self.parser.username = self.username
if self.parser.account_id is None:
self.parser.account_id = self.get_account_id()
if self.parser.account_id is None:
raise Exception("Own account is unknown")
result = self.parser.parse(data, lexer=self.lexer)
tables = self.findTables(result)
if gertty.db.project_table in tables:

View File

@ -136,8 +136,8 @@ def SearchParser():
def p_owner_term(p):
'''owner_term : OP_OWNER string'''
if p[2] == 'self':
username = p.parser.username
p[0] = gertty.db.account_table.c.username == username
account_id = p.parser.account_id
p[0] = gertty.db.account_table.c.id == account_id
else:
p[0] = or_(gertty.db.account_table.c.username == p[2],
gertty.db.account_table.c.email == p[2],
@ -156,8 +156,8 @@ def SearchParser():
if number is not None:
filters.append(gertty.db.account_table.c.id == number)
elif p[2] == 'self':
username = p.parser.username
filters.append(gertty.db.account_table.c.username == username)
account_id = p.parser.account_id
filters.append(gertty.db.account_table.c.id == account_id)
else:
filters.append(or_(gertty.db.account_table.c.username == p[2],
gertty.db.account_table.c.email == p[2],
@ -234,7 +234,7 @@ def SearchParser():
if user is not None:
filters.append(gertty.db.approval_table.c.account_key == gertty.db.account_table.c.key)
if user == 'self':
filters.append(gertty.db.account_table.c.username == p.parser.username)
filters.append(gertty.db.account_table.c.id == p.parser.account_id)
else:
filters.append(
or_(gertty.db.account_table.c.username == user,
@ -281,7 +281,7 @@ def SearchParser():
def p_is_term(p):
'''is_term : OP_IS string'''
#TODO: implement draft
username = p.parser.username
account_id = p.parser.account_id
if p[2] == 'reviewed':
filters = []
filters.append(gertty.db.approval_table.c.change_key == gertty.db.change_table.c.key)
@ -299,7 +299,7 @@ def SearchParser():
elif p[2] == 'abandoned':
p[0] = gertty.db.change_table.c.status == 'ABANDONED'
elif p[2] == 'owner':
p[0] = gertty.db.account_table.c.username == username
p[0] = gertty.db.account_table.c.id == account_id
elif p[2] == 'starred':
p[0] = gertty.db.change_table.c.starred == True
elif p[2] == 'held':
@ -309,7 +309,7 @@ def SearchParser():
filters = []
filters.append(gertty.db.approval_table.c.change_key == gertty.db.change_table.c.key)
filters.append(gertty.db.approval_table.c.account_key == gertty.db.account_table.c.key)
filters.append(gertty.db.account_table.c.username == username)
filters.append(gertty.db.account_table.c.id == account_id)
s = select([gertty.db.change_table.c.key], correlate=False).where(and_(*filters))
p[0] = gertty.db.change_table.c.key.in_(s)
elif p[2] == 'watched':

View File

@ -199,10 +199,12 @@ class SyncOwnAccountTask(Task):
remote = sync.get('accounts/self')
sync.account_id = remote['_account_id']
with app.db.getSession() as session:
session.getAccountByID(remote['_account_id'],
remote.get('name'),
remote.get('username'),
remote.get('email'))
account = session.getAccountByID(remote['_account_id'],
remote.get('name'),
remote.get('username'),
remote.get('email'))
session.setOwnAccount(account)
app.own_account_id = remote['_account_id']
class GetVersionTask(Task):
def __repr__(self):

View File

@ -172,7 +172,7 @@ class ReviewDialog(urwid.WidgetWrap, mywid.LineBoxTitlePropertyMixin):
draft_approvals = {}
prior_approvals = {}
for approval in change.approvals:
if approval.reviewer.username == self.app.config.username:
if self.app.isOwnAccount(approval.reviewer):
if approval.draft:
draft_approvals[approval.category] = approval
else:
@ -440,7 +440,7 @@ class ChangeMessageBox(mywid.HyperText):
if message.draft:
lines.insert(0, '')
lines.insert(0, 'Patch Set %s:' % (message.revision.number,))
if message.author.username == self.app.config.username:
if self.app.isOwnAccount(message.author):
name_style = 'change-message-own-name'
header_style = 'change-message-own-header'
reviewer_string = message.author_name
@ -748,7 +748,7 @@ class ChangeView(urwid.WidgetWrap):
if not approvals:
approvals = {}
row = []
if approval.reviewer.username == self.app.config.username:
if self.app.isOwnAccount(approval.reviewer):
style = 'reviewer-own-name'
else:
style = 'reviewer-name'

View File

@ -530,7 +530,7 @@ class BaseDiffView(urwid.WidgetWrap, mywid.Searchable):
raise Exception("Comment is not associated with a file")
with self.app.db.getSession() as session:
fileobj = session.getFile(file_key)
account = session.getAccountByUsername(self.app.config.username)
account = session.getOwnAccount()
comment = fileobj.createComment(None, account, None,
datetime.datetime.utcnow(),
parent,