Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PR featuring configuration, optional impersonation support, and optional last login support #17

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 68 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ A roles based account management system using bootstrap 3 for Meteor.
- [History](#history)
- [Quick Start](#quick-start)
- [Iron Router Integration](#iron-router-integration)
- [Configuration & Optional Features](#configuration)
- [Contributing](#contributing)

## TODO
Expand Down Expand Up @@ -111,7 +112,7 @@ if (Meteor.isClient) {
</div>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<ul class="nav navbar-nav">
</ul>
<ul class="nav navbar-nav navbar-right">
{{> loginButtons }}
Expand All @@ -137,9 +138,9 @@ After you edit app.js and app.html you need to create a new user and then set th
1. Go to [http://localhost:3000](http://localhost:3000) and click on the "Sign In / Up" and create your user there.
2. In the browser console grab the user id from the user you just created Meteor.userId()
3. Copy the user id and paste it into to "your_admin_user_id" in app.js created above.
4. Restart meteor
4. Restart meteor

At this point you should see the UI. Signout and add a few more users so you can play with the roles. You can add and
At this point you should see the UI. Signout and add a few more users so you can play with the roles. You can add and
remove roles all through the UI.

## Iron Router Integration
Expand Down Expand Up @@ -173,6 +174,69 @@ Router.map(function() {
});
});
```
## Configuration & Optional Features

**Configuration**
You can optionally configure this beyond the defaults by creating a accountsAdminUiConfiguration object anywhere in
the server/client shared part of your source code.

To change the number of users shown in the main accounts screen:

```javascript
accountsAdminUiConfiguration = {
maxUsersPerPage: 25, //max users to show in accounts_admin screen
};
```

**Impersonation**
Impersonation allows administrators to become a user without having login credentials for that user. It's very
handy for debugging user problems as ad administrator can experience you application as a user does. Iron Router is
required for it to automatically change to a different route on successful impersonation. To enable it you
need this minimum configuration:

```javascript
accountsAdminUiConfiguration = {
allowImpersonation: true, //true or the feature isn't enabled
impersonationRoles: ['admin'], //only this role(s) may use this impersonation feature
impersonationSuccessRoute: 'plansList', //once you have successfully impersonated a user, it will Router.go(impersonationSuccessRoute)
};
```

You will also want to put your impersonationSuccessRoute subscriptions in an Deps.autorun so that they change when the user changes.
Something like (though you need to change this for whatever makes sense for your routing configuration):
```javascript
this.route('plansList', {
onBeforeAction: function () {
var self = this;
Deps.autorun(function () {
var user = Meteor.user();
if (user) {
logger.debug("Subscribe for business and plans to user: " + user._id);
self.subscribe('plans').wait();
}
});
},
});
```
NOTE - This is an adminsitrative feature that allows a privileged user access beyond it's normal user. Use with caution.

Code inspired by: https://dweldon.silvrback.com/impersonating-a-user


**Last login support**
This feature requires the user-status (mrt add user-status) package. It shows the last login time for each user along with
a boolean indicating if they are logged in now. Enable with this configuration:

```javascript
accountsAdminUiConfiguration = {
userStatus: true, //if true and user-status pacakge installed, this will show last login and current login status
};
```






## Contributing

Expand All @@ -181,4 +245,4 @@ If you've got a change you think would benefit the community send me a pull requ
**Contributors**
- [@djkmiles](https://github.com/djkmiles)
- [@alanning](https://github.com/alanning)
- [@johnm](https://github.com/johnm)
- [@johnm](https://github.com/johnm)
113 changes: 66 additions & 47 deletions client/accounts_admin.html
Original file line number Diff line number Diff line change
@@ -1,49 +1,68 @@
<template name="accountsAdmin">
<div class="row accounts-search">
<div class="col-sm-offset-4 col-sm-8 col-md-offset-6 col-md-6 col-lg-offset-8 col-lg-4">
<div class="input-group">
<input type="text" class="form-control search-input-filter" value="{{searchFilter}}">
<span class="input-group-btn">
<button class="btn btn-default" type="button"><span class="glyphicon glyphicon-search"></span></button>
<button class="btn btn-default" type="button" data-toggle="modal" href="#updateroles">Manage Roles</button>
</span>
</div>
</div>

<div class="row accounts-search">
<div class="col-xs-offset-4 col-xs-8 col-md-offset-6 col-md-6 col-lg-offset-8 col-lg-4">
<div class="input-group">
<input type="text" class="form-control search-input-filter" value="{{searchFilter}}">
<span class="input-group-btn">
<button class="btn btn-default" type="button"><span class="glyphicon glyphicon-search"></span>
</button>
<button class="btn btn-default" type="button" data-toggle="modal" href="#updateroles">Manage Roles</button>
</span>
</div>
</div>
<table class='table table-striped'>
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Email</th>
<th>Roles</th>
</tr>
</thead>
<tbody>
{{#each users}}
<tr class="{{#if myself _id}}info{{/if}}">
<td>
{{#unless myself _id}}
<span data-toggle="modal" href="#deleteaccount" class="glyphicon glyphicon-trash clickable"></span>
<span data-toggle="modal" href="#updateaccount" class="glyphicon glyphicon-pencil clickable"></span>
<span data-toggle="modal" href="#infoaccount" class="glyphicon glyphicon-info-sign clickable"></span>
{{/unless}}
</td>
<td>
{{#if profile.name}}
{{profile.name}}
{{else}}
{{email}}
{{/if}}
</td>
<td>{{email}}</td>
<td>{{roles}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{> updateRolesModal}}
{{> deleteAccountModal}}
{{> infoAccountModal}}
{{> updateAccountModal}}
</template>
</div>
<table class='table table-striped'>
<thead>
<tr>
{{#each fields}}
<th>{{> accountsAdminHeader}}</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each users}}
<tr class="{{#if myself _id}}info{{/if}}">
{{#each fields}}
<td>{{> accountsAdminField field=. user=..}}</td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
<a href="#" class="showMore" data-direction="-1">Previous {{pageSize}} users</a>
<a href="#" class="showMore pull-right" data-direction="1">Next {{pageSize}} users</a>

{{> updateRolesModal}}
{{> deleteAccountModal}}
{{> infoAccountModal}}
{{> updateAccountModal}}
{{> impersonateAccountModal}}
</template>

<template name="accountsAdminHeader">
<a href="#" class="sortIndicator">{{header}}
{{#if sortDown}}
<span class="glyphicon glyphicon-chevron-down"></span>
{{/if}}
{{#if sortUp}}
<span class="glyphicon glyphicon-chevron-up"></span>
{{/if}}
</a>
</template>


<template name="accountsAdminControlPanel">
{{#unless myself _id}}
<span data-toggle="modal" href="#deleteaccount" class="glyphicon glyphicon-trash clickable"></span>
{{/unless}}
<span data-toggle="modal" href="#updateaccount" class="glyphicon glyphicon-pencil clickable"></span>
<span data-toggle="modal" href="#infoaccount" class="glyphicon glyphicon-info-sign clickable"></span>
{{#if allowImpersonate}}
<span data-toggle="modal" href="#impersonateaccount" class="glyphicon glyphicon-eye-open clickable"></span>
{{/if}}
</template>

<template name="accountsAdminField">
{{#if field.tmpl}} {{> field.tmpl}} {{else}} {{val}} {{/if}}
</template>
Loading