From b407c1d9fb926089c3dd0fa5651c14134d343b25 Mon Sep 17 00:00:00 2001 From: yackob03 Date: Wed, 20 Nov 2013 18:23:59 -0500 Subject: [PATCH] Add robots to the entity search. --- data/model.py | 17 +++++++++++++---- endpoints/api.py | 28 +++++++++++++++++----------- initdb.py | 4 ++++ static/js/app.js | 14 ++++++++------ static/js/controllers.js | 14 +++++++------- static/partials/repo-admin.html | 2 +- static/partials/team-view.html | 2 +- test/data/test.db | Bin 100352 -> 101376 bytes 8 files changed, 51 insertions(+), 30 deletions(-) diff --git a/data/model.py b/data/model.py index a18dc0af4..822605b92 100644 --- a/data/model.py +++ b/data/model.py @@ -379,11 +379,19 @@ def get_matching_teams(team_prefix, organization): return query.limit(10) -def get_matching_users(username_prefix, organization=None): +def get_matching_users(username_prefix, robot_namespace=None, + organization=None): Org = User.alias() - users_no_orgs = (User.username ** (username_prefix + '%') & - (User.organization == False)) - query = User.select(User.username, Org.username).where(users_no_orgs) + direct_user_query = (User.username ** (username_prefix + '%') & + (User.organization == False) & (User.robot == False)) + + if robot_namespace: + robot_prefix = format_robot_username(robot_namespace, username_prefix) + direct_user_query = (direct_user_query | + (User.username ** (robot_prefix + '%') & + (User.robot == True))) + + query = User.select(User.username, Org.username, User.robot).where(direct_user_query) if organization: with_team = query.join(TeamMember, JOIN_LEFT_OUTER).join(Team, @@ -396,6 +404,7 @@ def get_matching_users(username_prefix, organization=None): class MatchingUserResult(object): def __init__(self, *args): self.username = args[0] + self.is_robot = args[2] if organization: self.is_org_member = (args[1] == organization.username) else: diff --git a/endpoints/api.py b/endpoints/api.py index 185459094..202e723dd 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -260,20 +260,26 @@ def get_matching_users(prefix): def get_matching_entities(prefix): teams = [] - organization_name = request.args.get('organization', None) + namespace_name = request.args.get('namespace', None) + robot_namespace = None organization = None - if organization_name: - permission = OrganizationMemberPermission(organization_name) + try: + organization = model.get_organization(namespace_name) + + # namespace name was an org + permission = OrganizationMemberPermission(namespace_name) if permission.can(): - try: - organization = model.get_organization(organization_name) - except model.InvalidOrganizationException: - pass + robot_namespace = namespace_name - if organization: - teams = model.get_matching_teams(prefix, organization) + if request.args.get('includeTeams', False): + teams = model.get_matching_teams(prefix, organization) - users = model.get_matching_users(prefix, organization) + except model.InvalidOrganizationException: + # namespace name was a user + if current_user.db_user().username == namespace_name: + robot_namespace = namespace_name + + users = model.get_matching_users(prefix, robot_namespace, organization) def entity_team_view(team): result = { @@ -286,7 +292,7 @@ def get_matching_entities(prefix): def user_view(user): user_json = { 'name': user.username, - 'kind': 'user', + 'kind': 'robot' if user.is_robot else 'user', } if user.is_org_member is not None: diff --git a/initdb.py b/initdb.py index 5a2fbeb40..e810d8ab7 100644 --- a/initdb.py +++ b/initdb.py @@ -132,6 +132,8 @@ def populate_database(): new_user_1.verified = True new_user_1.save() + model.create_robot('dtrobot', new_user_1) + new_user_2 = model.create_user('public', 'password', 'jacob.moshenko@gmail.com') new_user_2.verified = True @@ -188,6 +190,8 @@ def populate_database(): org.stripe_id = TEST_STRIPE_ID org.save() + model.create_robot('neworgrobot', org) + owners = model.get_organization_team('buynlarge', 'owners') owners.description = 'Owners have unfetterd access across the entire org.' owners.save() diff --git a/static/js/app.js b/static/js/app.js index 26d7aa5da..04a887b8c 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -604,9 +604,10 @@ quayApp.directive('entitySearch', function () { transclude: false, restrict: 'C', scope: { - 'organization': '=organization', + 'namespace': '=namespace', 'inputTitle': '=inputTitle', - 'entitySelected': '=entitySelected' + 'entitySelected': '=entitySelected', + 'includeTeams': '=includeTeams' }, controller: function($scope, $element) { if (!$scope.entitySelected) { return; } @@ -614,15 +615,16 @@ quayApp.directive('entitySearch', function () { number++; var input = $element[0].firstChild; - $scope.organization = $scope.organization || ''; + $scope.namespace = $scope.namespace || ''; $(input).typeahead({ name: 'entities' + number, remote: { url: '/api/entities/%QUERY', replace: function (url, uriEncodedQuery) { url = url.replace('%QUERY', uriEncodedQuery); - if ($scope.organization) { - url += '?organization=' + encodeURIComponent($scope.organization); + url += '?namespace=' + encodeURIComponent($scope.namespace); + if ($scope.includeTeams) { + url += '&includeTeams=true' } return url; }, @@ -648,7 +650,7 @@ quayApp.directive('entitySearch', function () { } template += '' + datum.value + ''; - if (datum.entity.is_org_member !== undefined && !datum.entity.is_org_member) { + if (datum.entity.is_org_member !== undefined && !datum.entity.is_org_member && datum.kind == 'user') { template += '
This user is outside your organization
'; } diff --git a/static/js/controllers.js b/static/js/controllers.js index 8bba4f712..a83f375a2 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -1296,7 +1296,7 @@ function TeamViewCtrl($rootScope, $scope, Restangular, $routeParams) { 'html': true }); - var orgname = $routeParams.orgname; + $scope.orgname = $routeParams.orgname; var teamname = $routeParams.teamname; $rootScope.title = 'Loading...'; @@ -1307,7 +1307,7 @@ function TeamViewCtrl($rootScope, $scope, Restangular, $routeParams) { if ($scope.members[member.name]) { return; } $scope.$apply(function() { - var addMember = Restangular.one(getRestUrl('organization', orgname, 'team', teamname, 'members', member.name)); + var addMember = Restangular.one(getRestUrl('organization', $scope.orgname, 'team', teamname, 'members', member.name)); addMember.customPOST().then(function(resp) { $scope.members[member.name] = resp; }, function() { @@ -1317,7 +1317,7 @@ function TeamViewCtrl($rootScope, $scope, Restangular, $routeParams) { }; $scope.removeMember = function(username) { - var removeMember = Restangular.one(getRestUrl('organization', orgname, 'team', teamname, 'members', username)); + var removeMember = Restangular.one(getRestUrl('organization', $scope.orgname, 'team', teamname, 'members', username)); removeMember.customDELETE().then(function(resp) { delete $scope.members[username]; }, function() { @@ -1328,7 +1328,7 @@ function TeamViewCtrl($rootScope, $scope, Restangular, $routeParams) { $scope.updateForDescription = function(content) { $scope.organization.teams[teamname].description = content; - var updateTeam = Restangular.one(getRestUrl('organization', orgname, 'team', teamname)); + var updateTeam = Restangular.one(getRestUrl('organization', $scope.orgname, 'team', teamname)); var data = $scope.organization.teams[teamname]; updateTeam.customPUT(data).then(function(resp) { }, function() { @@ -1337,7 +1337,7 @@ function TeamViewCtrl($rootScope, $scope, Restangular, $routeParams) { }; var loadOrganization = function() { - var getOrganization = Restangular.one(getRestUrl('organization', orgname)) + var getOrganization = Restangular.one(getRestUrl('organization', $scope.orgname)) getOrganization.get().then(function(resp) { $scope.organization = resp; $scope.team = $scope.organization.teams[teamname]; @@ -1350,12 +1350,12 @@ function TeamViewCtrl($rootScope, $scope, Restangular, $routeParams) { }; var loadMembers = function() { - var getMembers = Restangular.one(getRestUrl('organization', orgname, 'team', teamname, 'members')); + var getMembers = Restangular.one(getRestUrl('organization', $scope.orgname, 'team', teamname, 'members')); getMembers.get().then(function(resp) { $scope.members = resp.members; $scope.canEditMembers = resp.can_edit; $scope.loading = !$scope.organization || !$scope.members; - $rootScope.title = teamname + ' (' + orgname + ')'; + $rootScope.title = teamname + ' (' + $scope.orgname + ')'; }, function() { $scope.organization = null; $scope.members = null; diff --git a/static/partials/repo-admin.html b/static/partials/repo-admin.html index d9016b83a..89442c88f 100644 --- a/static/partials/repo-admin.html +++ b/static/partials/repo-admin.html @@ -91,7 +91,7 @@ - + diff --git a/static/partials/team-view.html b/static/partials/team-view.html index 6d7084b3e..1d8d66d5c 100644 --- a/static/partials/team-view.html +++ b/static/partials/team-view.html @@ -33,7 +33,7 @@ - + diff --git a/test/data/test.db b/test/data/test.db index 6a2cb0c869049a5802a332d49c5cb6c7124f7aea..fdb9329a01d83bc1012a996d0e100dbe7a96a2a9 100644 GIT binary patch delta 3810 zcmbtXd2kcg8Q<@{)gBfY3^MYGWk+BeUpj0_#tz(+GwB~4 zJnP?n``)+T`;OoD-s;f9+@VLghtrd`F$^Q8;byqjrP2IjO zM{lFmS>v^K+gog&W`D2U($Z$~G}Jgv=2l-zo8RMf_q12n)zq3??H(JSz+^Ecf>{*E z-^+_8`Zz68*5Zz0liy)= z9%$V&6y9&!KhZkcSYE%+wBKj9?iv~F8rEDlFU zw@Z?L+A}sV7?KJCV`{uUXOU(LXH+iNKdL0Vj z5WI;##Ro|e8`d`@a{BCK2=0gkqXGO5Z=Cg)s=%3H2tQrILAzVSM&CN~?cpjT&W zn#$=rUu&{)DbDt~>JC!gluq7mDoBZk{Hl_-+abS-U#B6T!!$<>2;{AXHRS!*a&!W^ z&Ye}7*QtU&|Pgej>&i3U{{B@soO}xr(hH*m+yntBLgkHms z%GrfrLlema+&V}lYutZD!)wUafDzKkWS}Nf&*|4CLsYH*m^2Wk^$$sXI|7QFK{ZyB ze+079QaF89G7R0;iVTD$MI}>JsgzQw?H(x~)~dCARH}hAGA|h*i+nDfC5gcl@~t3G zih@S+mto^n|4q#Eh{YiCQ`b<~3M@ zm50v`YFM2TDaZI2dc6$w$cui3n<$$r(QpP?5zK>Z^5$?V@dnpJCfOG>!9A)|v%wmC zSXfJPkLH1qv>m-noiiUZkxR$cl8IyaU?AT=W+kEH0{P>ydTOKKcs0p5VIq$mubDb@ z4QFT&=2@UlAjGnwD8`TR5QAUDAU9kzr*h}w@-_>gVz~+6JL)d z34g-(sOd)n;%FH}gyJ-Kh+!Ur4e$)*%NKYbrNIcE%+4WyI9>sHYTYd-yp#b)P8eVV zdFsR#wADy@P8*?sJaD=k){&P^8=#QfcQu7vKRpBM$+@SBp@>|cP9Zm*vO+G|aHa%` zRYTD;Ra1|#LX3Up)QS+tV_xLw=NyQfC{TeiL!-eW9~ZF(@mzdbBWTny5wkoSAHpJD zRHK}tq*1IOj@F!6cI~ju>Z+$rRFUr2BCzq^z45bzWvi5;X&Cy!ypj15evVV{VH#Z?skmUIcIlZx zmp^);fXW`4^?NTgfqgOe3FL_xE%iHDu0+7eRauZg`eqZ!pD(20!`>3Iy_ z0WgstzMBi>>WhDSw-C%EW!^;Q<}*lO-gI(~i*awhh;1C7z_B6#C#t;CXoPrsYj|~7 z!^Iz2jryn*Pig+x$8S&Jt#zJue|4|VVR6(ndVLKY_Uaa!yQi$7yt~t3YH4$LYwE2% z)!sV4r?t1UzN5an)7$B=^!7H^+efH6_;DB_HsL# zx-^HY?skEx%dD`BWj5p$A0BeUSw%3q$9Z32+cWpL{d{+^|J{N4fcBgO=XBa!9$goqtISE@AP&nqrtK z$cN`p8_vfkX=IP1@d`PxmKt7}1)1`5Yw5??Ci&7@>ZD6f$^tKJmWQ&S92%E;K%UNm zT0Gf#ul&tSNP{N%=}dST1uNy8Od7FUjcjWs6roU+{G$xWgJ$`68Q?rQ$3D&KKse7D I;Pc>r0O5V`v;Y7A delta 3020 zcmbtWdvFuS9lqc0-AN~dABlx5Kd|g5*aj@?X;~P8E#rqQ+gN^LhX9g%mSpQ;B#ZD! zAO-_TI_*F<>9v_Og}6yOOwu$`9_ihw_5@Tcj5Wq-$N0WhNtgrTIMEJ0XbZ? z58anb&UI8k0lD7Mn5t&;^Le<;;HPjsx`-Y?rEoc2z`hGA8!s^BOr6pskZ(F_4{YO9 zOvMaWBQQ#3EIFMBjft^%KyUWyO=kT_eZu1&Z5ecR$IQuYPi%T}=TxgWZ0>3?j5<2D znCo}-kM3=6F?93|wok|R+C9CY-Tl#+xoJA+jZP*E{#ay`RWaHn{ zN8f?^q{-lkc#O8rJ#I^nb@SA8ysyD2PPz=O@qX{P&28*;P9+Vy!aaQ>-4m4DbQ}3r ztYXS%xGH(_<8d(&OeVhM57|up9S#1(bbZ9!H#rtITKt9)!_JZMfuME7GTa{RHcYfP zAE;~bCW9@a-8Q__Gr2bsjon5+hB9;CAk$AJec_OQY3>F`S8v!g>Yp0h6YgvuwRMM* zVrw$cKV{w&jTrg@_Fzxlu1KhPcfga_6YQ932-I2nC%pcc&k%_vf?{+s))a_%Lt#Td zmB{#kSj4Z?rHP2g~*l0qI@2w8JxzS;P>(C_(S{-b^iCUcR4NxUvf`0?2QLR zJ{MQOS3c)dSPNMfvGRLg3X0{9?D|m-E)%|(qa3k3zQo{L_@DS=d=>uB1I2l+OunY)erI7vX-P=EVmwt8zH?P1Z@Fx@7&C`)+(9%1(#na!=(@u#PnTU~z zX!giJi5NjnCZ4Hb=((Rc2RG23C-Omq`twMws|@ZSZdZLtKCh`zLoyT{6L-tOv0ap9 zms^FTsX|R&a>*IPI= zN%p(ziNUQT8{ArQ-o2)1=0IU48xMIi&YKp!5&0@2{;`h=v+I43!EaH4p2GzH3_nQM z8^QfYq~x1*#cZe-?}YWaVg#a|1-uYDbiq@Fp=;F zWAXTxqor^4zmNw!IpwdU_#3|^75ogB^N7WetyD^8l%eMvPyoYl5j~5S<0L6yooHN5 zHj8@Dl4;SYUcqbbRzoZ!vApW-@mN?SVX=h#RV-I)culz){9pA(y%CX|6N`v>Tnj~{ zYrF=^GSYry+({YFjq6|~xi)?Zipi6KYA7fBXSF2nu!39)l%eqwGB{gJ-Ut*EX?7Kq zlKEL9d2m)q+ADGid)S!@f1H!cqa0QXLhSyi7*Fu2-Pf_eBDyRF0Hr_McM~gE%whTA z<^hgfnc{8vOwuq#^gU= zBiYIS{zNgEKkCFY6&2)>6OH6sM~&pg6AE(kgprc3J*k6g(tYyYR6d(O$NoT>%Q1A5 z8fIRB7f=;?k$R;SZM}<}I;n>m^7csw9a(rr2W!aj(?!Jj%o(`*u{i^*mAta%?Q<4b zMfT0rL2X9)g}Ektu&0V_J#7U;`uJ%rq@I5+ZDPL&yJ z+oJlvcrGuNlJ$#~nKAcM-ha&(lB0`jmY&-lyU3^cU%ZJcIh9-l1v$=GWhUBa)X}P# zY0_#YfONea3e)VHw{lV!Pvd${q2gHqfEO}R$a2bTG;)fJnd7sMESGu2RA@O?(;vT| z!r{%Pk&Xddo6+WI8EkO08C`unPMdSU&GSM`AVJ#TR>;)q@NdDCl^3DY#nlO>eS5}jkFO-tc zukgflb!F;<1>E%i&O7xNR+(n6-@^HsSu#fY2L@+Q7y1)T2pvA8GLycmtD#ZOg7gzt zT>uvH$A2`C2d*x~lkwUHu#)JtbwqQmoIH9hkNoc1>f(c?Hibr`fmuzaoQERbfS7@e zuY4CcNPUu{1n=>w!nE$z_poP26IE!t9J}|~DQq=UxVM(VFx{G%p}Q#zR#50KqtK_N z;F13bd-5oB%bP1MllIx_Gi)g`Zm1|Y$x3#ba8l|;buu7MTpiIgy&aNzz+Lf?gN^8LZ?Mrn` NB`qt4P0#5e_#gZ3EkytT