1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-20 05:39:42 +02:00

Set user admin max results and Keycloak sync option

This commit is contained in:
McMatts 2018-08-20 17:17:25 +01:00
parent 2c8b757ff6
commit 351b8dcc12
13 changed files with 100 additions and 31 deletions

View file

@ -94,7 +94,7 @@ func (h *Handler) Sync(w http.ResponseWriter, r *http.Request) {
} }
// User list from Documize // User list from Documize
dmzUsers, err := h.Store.User.GetUsersForOrganization(ctx, "") dmzUsers, err := h.Store.User.GetUsersForOrganization(ctx, "", 99999)
if err != nil { if err != nil {
result.Message = "Error: unable to fetch Documize users" result.Message = "Error: unable to fetch Documize users"
result.IsError = true result.IsError = true

View file

@ -115,7 +115,7 @@ type UserStorer interface {
GetByToken(ctx RequestContext, token string) (u user.User, err error) GetByToken(ctx RequestContext, token string) (u user.User, err error)
GetBySerial(ctx RequestContext, serial string) (u user.User, err error) GetBySerial(ctx RequestContext, serial string) (u user.User, err error)
GetActiveUsersForOrganization(ctx RequestContext) (u []user.User, err error) GetActiveUsersForOrganization(ctx RequestContext) (u []user.User, err error)
GetUsersForOrganization(ctx RequestContext, filter string) (u []user.User, err error) GetUsersForOrganization(ctx RequestContext, filter string, limit int) (u []user.User, err error)
GetSpaceUsers(ctx RequestContext, spaceID string) (u []user.User, err error) GetSpaceUsers(ctx RequestContext, spaceID string) (u []user.User, err error)
GetUsersForSpaces(ctx RequestContext, spaces []string) (u []user.User, err error) GetUsersForSpaces(ctx RequestContext, spaces []string) (u []user.User, err error)
UpdateUser(ctx RequestContext, u user.User) (err error) UpdateUser(ctx RequestContext, u user.User) (err error)

View file

@ -248,6 +248,11 @@ func (h *Handler) GetOrganizationUsers(w http.ResponseWriter, r *http.Request) {
active = false active = false
} }
limit, _ := strconv.Atoi(request.Query(r, "limit"))
if limit == 0 {
limit = 100
}
u := []user.User{} u := []user.User{}
if active { if active {
@ -258,7 +263,7 @@ func (h *Handler) GetOrganizationUsers(w http.ResponseWriter, r *http.Request) {
return return
} }
} else { } else {
u, err = h.Store.User.GetUsersForOrganization(ctx, filter) u, err = h.Store.User.GetUsersForOrganization(ctx, filter, limit)
if err != nil && err != sql.ErrNoRows { if err != nil && err != sql.ErrNoRows {
response.WriteServerError(w, method, err) response.WriteServerError(w, method, err)
h.Runtime.Log.Error(method, err) h.Runtime.Log.Error(method, err)

View file

@ -132,7 +132,7 @@ func (s Scope) GetActiveUsersForOrganization(ctx domain.RequestContext) (u []use
// GetUsersForOrganization returns a slice containing all of the user records for the organizaiton // GetUsersForOrganization returns a slice containing all of the user records for the organizaiton
// identified in the Persister. // identified in the Persister.
func (s Scope) GetUsersForOrganization(ctx domain.RequestContext, filter string) (u []user.User, err error) { func (s Scope) GetUsersForOrganization(ctx domain.RequestContext, filter string, limit int) (u []user.User, err error) {
u = []user.User{} u = []user.User{}
filter = strings.TrimSpace(strings.ToLower(filter)) filter = strings.TrimSpace(strings.ToLower(filter))
@ -146,7 +146,7 @@ func (s Scope) GetUsersForOrganization(ctx domain.RequestContext, filter string)
u.global, a.active, a.editor, a.admin, a.users AS viewusers, a.analytics u.global, a.active, a.editor, a.admin, a.users AS viewusers, a.analytics
FROM user u, account a FROM user u, account a
WHERE u.refid=a.userid AND a.orgid=? `+likeQuery+ WHERE u.refid=a.userid AND a.orgid=? `+likeQuery+
`ORDER BY u.firstname, u.lastname LIMIT 100`, ctx.OrgID) `ORDER BY u.firstname, u.lastname LIMIT `+strconv.Itoa(limit), ctx.OrgID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
err = nil err = nil

View file

@ -34,8 +34,11 @@ export default Base.extend({
authenticate(data) { authenticate(data) {
data.domain = netUtil.getSubdomain(); data.domain = netUtil.getSubdomain();
if (!isPresent(data.token) || !isPresent(data.email)) { if (!isPresent(data.token)) {
return reject("invalid"); return reject("data.token is empty");
}
if (!isPresent(data.email)) {
return reject("data.email is empty");
} }
return this.get('ajax').post('public/authenticate/keycloak', { return this.get('ajax').post('public/authenticate/keycloak', {

View file

@ -12,9 +12,9 @@
import $ from 'jquery'; import $ from 'jquery';
import { inject as service } from '@ember/service'; import { inject as service } from '@ember/service';
import { schedule, debounce } from '@ember/runloop'; import { schedule, debounce } from '@ember/runloop';
import Component from '@ember/component';
import AuthProvider from '../../mixins/auth'; import AuthProvider from '../../mixins/auth';
import ModalMixin from '../../mixins/modal'; import ModalMixin from '../../mixins/modal';
import Component from '@ember/component';
export default Component.extend(AuthProvider, ModalMixin, { export default Component.extend(AuthProvider, ModalMixin, {
groupSvc: service('group'), groupSvc: service('group'),
@ -230,6 +230,15 @@ export default Component.extend(AuthProvider, ModalMixin, {
this.get('groupSvc').join(groupId, userId).then(() => { this.get('groupSvc').join(groupId, userId).then(() => {
this.filterUsers(); this.filterUsers();
}); });
},
onSync() {
this.get('onSync')();
},
onLimit(limit) {
this.set('userLimit', limit);
this.filterUsers();
} }
} }
}); });

View file

@ -41,7 +41,11 @@ export default Route.extend({
this.get("session").authenticate('authenticator:keycloak', data).then(() => { this.get("session").authenticate('authenticator:keycloak', data).then(() => {
this.transitionTo('folders'); this.transitionTo('folders');
}, (reject) => { }, (reject) => {
if (is.not.undefined(reject.Error)) {
this.set('message', reject.Error); this.set('message', reject.Error);
} else {
this.set('message', reject);
}
this.set('mode', 'reject'); this.set('mode', 'reject');
resolve(); resolve();
}); });

View file

@ -14,9 +14,12 @@ import Controller from '@ember/controller';
export default Controller.extend({ export default Controller.extend({
userService: service('user'), userService: service('user'),
globalSvc: service('global'),
syncInProgress: false,
userLimit: 100,
loadUsers(filter) { loadUsers(filter) {
this.get('userService').getComplete(filter).then((users) => { this.get('userService').getComplete(filter, this.get('userLimit')).then((users) => {
this.set('model', users); this.set('model', users);
}); });
}, },
@ -52,6 +55,14 @@ export default Controller.extend({
onFilter(filter) { onFilter(filter) {
this.loadUsers(filter); this.loadUsers(filter);
},
onSync() {
this.set('syncInProgress', true);
this.get('globalSvc').syncExternalUsers().then(() => {
this.set('syncInProgress', false);
this.loadUsers('');
});
} }
} }
}); });

View file

@ -16,7 +16,6 @@ import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-rout
export default Route.extend(AuthenticatedRouteMixin, { export default Route.extend(AuthenticatedRouteMixin, {
userService: service('user'), userService: service('user'),
global: service('global'),
appMeta: service(), appMeta: service(),
beforeModel () { beforeModel () {
@ -27,20 +26,10 @@ export default Route.extend(AuthenticatedRouteMixin, {
model() { model() {
return new EmberPromise((resolve) => { return new EmberPromise((resolve) => {
let constants = this.get('constants'); this.get('userService').getComplete('', 100).then((users) => {
if (this.get('appMeta.authProvider') == constants.AuthProvider.Keycloak) {
this.get('global').syncExternalUsers().then(() => {
this.get('userService').getComplete('').then((users) =>{
resolve(users); resolve(users);
}); });
}); });
} else {
this.get('userService').getComplete('').then((users) => {
resolve(users);
});
}
});
}, },
activate() { activate() {

View file

@ -3,6 +3,9 @@
onAddUsers=(action 'onAddUsers')}} onAddUsers=(action 'onAddUsers')}}
{{customize/user-list users=model {{customize/user-list users=model
syncInProgress=syncInProgress
userLimit=userLimit
onSync=(action "onSync")
onFilter=(action "onFilter") onFilter=(action "onFilter")
onDelete=(action "onDelete") onDelete=(action "onDelete")
onSave=(action "onSave") onSave=(action "onSave")

View file

@ -68,11 +68,12 @@ export default Service.extend({
// Returns all active and inactive users for organization. // Returns all active and inactive users for organization.
// Only available for admins and limits results to max. 100 users. // Only available for admins and limits results to max. 100 users.
// Takes filter for user search criteria. // Takes filter for user search criteria.
getComplete(filter) { getComplete(filter, limit) {
filter = filter.trim(); filter = filter.trim();
if (filter.length > 0) filter = encodeURIComponent(filter); if (filter.length > 0) filter = encodeURIComponent(filter);
if (is.null(limit) || is.undefined(limit)) limit = 100;
return this.get('ajax').request(`users?active=0&filter=${filter}`).then((response) => { return this.get('ajax').request(`users?active=0&filter=${filter}&limit=${limit}`).then((response) => {
if (is.not.array(response)) response = []; if (is.not.array(response)) response = [];
return response.map((obj) => { return response.map((obj) => {

View file

@ -157,4 +157,8 @@
} }
} }
} }
> .max-results {
float: right;
}
} }

View file

@ -1,4 +1,11 @@
<div class="view-customize my-5"> <div class="view-customize my-5">
{{#if isAuthProviderKeycloak}}
{{#if syncInProgress}}
<div class="btn btn-secondary mt-3 mb-3">Keycloak user sync running...</div>
{{else}}
<div class="btn btn-success mt-3 mb-3" {{action 'onSync'}}>Sync with Keycloak</div>
{{/if}}
{{/if}}
<div class="my-2"> <div class="my-2">
<span class="font-weight-bold">Spaces</span> <span class="font-weight-bold">Spaces</span>
@ -26,6 +33,39 @@
<small class="form-text text-muted">search firstname, lastname, email</small> <small class="form-text text-muted">search firstname, lastname, email</small>
</div> </div>
<div class="max-results py-3">
<div class="btn-group btn-group-toggle">
<label class="btn btn-outline-secondary {{if (eq userLimit 1) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 1}}>1
</label>
<label class="btn btn-outline-secondary {{if (eq userLimit 10) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 10}}>10
</label>
<label class="btn btn-outline-secondary {{if (eq userLimit 25) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 25}}>25
</label>
<label class="btn btn-outline-secondary {{if (eq userLimit 50) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 50}}>50
</label>
<label class="btn btn-outline-secondary {{if (eq userLimit 100) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 100}}>100
</label>
<label class="btn btn-outline-secondary {{if (eq userLimit 250) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 250}}>250
</label>
<label class="btn btn-outline-secondary {{if (eq userLimit 500) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 500}}>500
</label>
<label class="btn btn-outline-secondary {{if (eq userLimit 1000) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 1000}}>1,000
</label>
<label class="btn btn-outline-secondary {{if (eq userLimit 99999) 'active'}}">
<input type="radio" name="options" autocomplete="off" {{action 'onLimit' 99999}}>all
</label>
</div>
</div>
<table class="table table-responsive table-borderless user-table"> <table class="table table-responsive table-borderless user-table">
<thead> <thead>
<tr> <tr>