Merge branch 'master' into fixes/query-tables

This commit is contained in:
Zsolt Kocsmarszky 2017-12-06 21:31:54 +01:00
commit 69badf67fc
15 changed files with 65 additions and 20 deletions

View File

@ -299,6 +299,14 @@ page-header, .page-header--new {
border-radius: 100%;
}
.profile__image_thumb {
border-radius: 100%;
margin-right: 3px;
margin-top: -2px;
width: 20px;
height: 20px;
}
.btn__new {
margin-left: 15px;
}

View File

@ -57,7 +57,7 @@
<!--</li>-->
<li class="dropdown" uib-dropdown>
<a href="#" class="dropdown-toggle dropdown--profile" uib-dropdown-toggle>
<img ng-src="{{$ctrl.currentUser.gravatar_url}}" class="profile__image--navbar" width="20"/>
<img ng-src="{{$ctrl.currentUser.profile_image_url}}" class="profile__image--navbar" width="20"/>
<span class="dropdown--profile__username" ng-bind="$ctrl.currentUser.name"></span> <span
class="caret caret--nav"></span></a>
<ul class="dropdown-menu dropdown-menu--profile">

View File

@ -11,7 +11,7 @@
refresh-delay="0"
ui-disable-choice="user.alreadyGrantee">
<div>
<img ng-src="{{user.gravatar_url}}" height="24px">&nbsp;{{user.name}}
<img ng-src="{{user.profile_image_url}}" height="24px">&nbsp;{{user.name}}
<small ng-if="user.alreadyGrantee">(already has permission)</small>
</div>
</ui-select-choices>
@ -28,7 +28,7 @@
</thead>
<tbody>
<tr ng-repeat="grantee in $ctrl.grantees">
<td width="50px"><img ng-src="{{grantee.gravatar_url}}" height="40px"/></td>
<td width="50px"><img ng-src="{{grantee.profile_image_url}}" height="40px"/></td>
<td>{{grantee.name}} </td>
<td>{{grantee.access_type}}</td>
<td><button class="pull-right btn btn-sm btn-danger" ng-click="$ctrl.removeGrantee(grantee)">Remove</button></td>

View File

@ -17,7 +17,7 @@
refresh-delay="0"
ui-disable-choice="user.alreadyMember">
<div>
<img ng-src="{{user.gravatar_url}}" height="24px">&nbsp;{{user.name}}
<img ng-src="{{user.profile_image_url}}" height="24px">&nbsp;{{user.name}}
<small ng-if="user.alreadyMember">(already member in this group)</small>
</div>
</ui-select-choices>
@ -29,7 +29,7 @@
<table class="table table-condensed table-hover" ng-show="members">
<tbody>
<tr ng-repeat="member in members">
<td width="50px"><img ng-src="{{member.gravatar_url}}" height="40px"/></td>
<td width="50px"><img ng-src="{{member.profile_image_url}}" height="40px"/></td>
<td>{{member.name}} <button class="pull-right btn btn-sm btn-danger" ng-click="removeMember(member)" ng-if="currentUser.isAdmin && (group.type != 'builtin' || currentUser.id != member.id)">Remove</button></td>
</tr>
</tbody>

View File

@ -17,7 +17,10 @@
<tbody>
<tr ng-repeat="query in $ctrl.paginator.getPageRows()">
<td><a href="queries/{{query.id}}">{{query.name}}</a> <span class="label label-default" ng-if="query.is_draft">Unpublished</span></td>
<td>{{query.user.name}}</td>
<td>
<img ng-src="{{query.user.profile_image_url}}" class="profile__image_thumb"/>
{{query.user.name}}
</td>
<td>{{query.created_at | dateTime}}</td>
<td>{{query.runtime | durationHumanize}}</td>
<td>{{query.retrieved_at | dateTime}}</td>

View File

@ -24,7 +24,9 @@
<tbody>
<tr ng-repeat="query in $ctrl.paginator.getPageRows()">
<td><a href="queries/{{query.id}}">{{query.name}}</a> <span class="label label-default" ng-if="query.is_draft">Unpublished</span></td>
<td>{{query.user.name}}</td>
<td>
<img ng-src="{{query.user.profile_image_url}}" class="profile__image_thumb"/>
{{query.user.name}}</td>
<td>{{query.created_at | dateTime}}</td>
<td>{{query.schedule | scheduleHumanize}}</td>
</tr>

View File

@ -40,6 +40,7 @@
<li>
<span class="zmdi zmdi-account"></span>
<span class="text-muted">Created By </span>
<img ng-src="{{query.user.profile_image_url}}" class="profile__image_thumb"/>
<strong>{{query.user.name}}</strong>
</li>
<li ng-if="query.last_modified_by && query.user.id != query.last_modified_by.id">

View File

@ -22,7 +22,9 @@
<button class="btn btn-danger" ng-if="$ctrl.snippet.id" ng-click="$ctrl.delete()">Delete</button>
</div>
<small ng-if="$ctrl.snippet.user">
Created by: {{$ctrl.snippet.user.name}}
Created by:
<img ng-src="{{$ctrl.snippet.user.profile_image_url}}" class="profile__image_thumb"/>
{{$ctrl.snippet.user.name}}
</small>
</form>
</div>

View File

@ -27,6 +27,7 @@
{{row.snippet}}
</td>
<td>
<img ng-src="{{row.user.profile_image_url}}" class="profile__image_thumb"/>
{{row.user.name}}
</td>
<td>

View File

@ -15,7 +15,7 @@
<tbody>
<tr ng-repeat="row in $ctrl.users.getPageRows()">
<td>
<img ng-src="{{row.gravatar_url}}" height="32px" class="profile__image--settings"/> <a href="users/{{row.id}}">{{row.name}}</a>
<img ng-src="{{row.profile_image_url}}" height="32px" class="profile__image--settings"/> <a href="users/{{row.id}}">{{row.name}}</a>
</td>
<td>
<span am-time-ago="row.created_at"></span>

View File

@ -5,7 +5,7 @@
<div class="row">
<div class="col-md-4 col-md-offset-4 profile__cointainer">
<img ng-src="{{user.gravatar_url}}" class="profile__image"/>
<img ng-src="{{user.profile_image_url}}" class="profile__image"/>
<h3 class="profile__h3">{{user.name}}</h3>

View File

@ -0,0 +1,25 @@
"""empty message
Revision ID: 7671dca4e604
Revises: d1eae8b9893e
Create Date: 2017-11-22 22:20:25.166045
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '7671dca4e604'
down_revision = 'd1eae8b9893e'
branch_labels = None
depends_on = None
def upgrade():
op.add_column('users', sa.Column('profile_image_url', sa.String(),
nullable=True, server_default=None))
def downgrade():
op.drop_column('users', 'profile_image_url')

View File

@ -58,7 +58,7 @@ def verify_profile(org, profile):
return False
def create_and_login_user(org, name, email):
def create_and_login_user(org, name, email, picture=None):
try:
user_object = models.User.get_by_email_and_org(email, org)
if user_object.name != name:
@ -67,7 +67,8 @@ def create_and_login_user(org, name, email):
models.db.session.commit()
except NoResultFound:
logger.debug("Creating user object (%r)", name)
user_object = models.User(org=org, name=name, email=email, group_ids=[org.default_group.id])
user_object = models.User(org=org, name=name, email=email, _profile_image_url=picture,
group_ids=[org.default_group.id])
models.db.session.add(user_object)
models.db.session.commit()
@ -116,7 +117,8 @@ def authorized():
flash("Your Google Apps account ({}) isn't allowed.".format(profile['email']))
return redirect(url_for('redash.login', org_slug=org.slug))
create_and_login_user(org, profile['name'], profile['email'])
picture_url = "%s?sz=40" % profile['picture']
create_and_login_user(org, profile['name'], profile['email'], picture_url)
next_path = request.args.get('state') or url_for("redash.index", org_slug=org.slug)

View File

@ -191,11 +191,8 @@ def session(org_slug=None):
'apiKey': current_user.id
}
else:
email_md5 = hashlib.md5(current_user.email.lower()).hexdigest()
gravatar_url = "https://www.gravatar.com/avatar/%s?s=40" % email_md5
user = {
'gravatar_url': gravatar_url,
'profile_image_url': current_user.profile_image_url,
'id': current_user.id,
'name': current_user.name,
'email': current_user.email,

View File

@ -395,6 +395,7 @@ class User(TimestampMixin, db.Model, BelongsToOrgMixin, UserMixin, PermissionsCh
org = db.relationship(Organization, backref=db.backref("users", lazy="dynamic"))
name = Column(db.String(320))
email = Column(LowercasedString)
_profile_image_url = Column('profile_image_url', db.String(320), nullable=True)
password_hash = Column(db.String(128), nullable=True)
# XXX replace with association table
group_ids = Column('groups', MutableList.as_mutable(postgresql.ARRAY(db.Integer)), nullable=True)
@ -415,7 +416,7 @@ class User(TimestampMixin, db.Model, BelongsToOrgMixin, UserMixin, PermissionsCh
'id': self.id,
'name': self.name,
'email': self.email,
'gravatar_url': self.gravatar_url,
'profile_image_url': self.profile_image_url,
'groups': self.group_ids,
'updated_at': self.updated_at,
'created_at': self.created_at
@ -435,9 +436,12 @@ class User(TimestampMixin, db.Model, BelongsToOrgMixin, UserMixin, PermissionsCh
return False
@property
def gravatar_url(self):
def profile_image_url(self):
if self._profile_image_url is not None:
return self._profile_image_url
email_md5 = hashlib.md5(self.email.lower()).hexdigest()
return "https://www.gravatar.com/avatar/%s?s=40" % email_md5
return "https://www.gravatar.com/avatar/{}?s=40&d=identicon".format(email_md5)
@property
def permissions(self):