added pages to add / edit / delete users from the system

This commit is contained in:
Brad Rydzewski 2014-07-09 14:25:11 -07:00
parent 79e46d1a8c
commit 6b9ae21c7a
11 changed files with 284 additions and 4 deletions

View file

@ -50,8 +50,28 @@ app.config(['$routeProvider', '$locationProvider', function($routeProvider, $loc
}
}
})
.when('/admin/users/add', {
templateUrl: '/views/users_add.html',
controller: 'UserAddController',
title: 'Add User',
resolve: {
user: function(authService) {
return authService.getUser();
}
}
})
.when('/admin/users/:host/:login', {
templateUrl: '/views/users_edit.html',
controller: 'UserEditController',
title: 'Edit User',
resolve: {
user: function(authService) {
return authService.getUser();
}
}
})
.when('/admin/users', {
templateUrl: '/views/sys_users.html',
templateUrl: '/views/users.html',
controller: 'UsersController',
title: 'System Users',
resolve: {

View file

@ -11,4 +11,45 @@ angular.module('app').controller("UsersController", function($scope, $http, user
error(function(data, status, headers, config) {
console.log(data);
});
});
angular.module('app').controller("UserAddController", function($scope, $http, users) {
// set the default host to github ... however ...
// eventually we can improve this logic to use the hostname
// of the currently authenticated user.
$scope.host='github.com';
$scope.name='';
$scope.create = function() {
users.create($scope.host, $scope.name).success(function () {
window.location.href="/admin/users";
})
.error(function (error) {
console.log(error);
});
};
});
angular.module('app').controller("UserEditController", function($scope, $http, $routeParams, users) {
var host = $routeParams.host;
var name = $routeParams.login;
users.get(host, name).success(function (user) {
$scope.account = user;
$scope.state = 1;
})
.error(function (error) {
$scope.account = undefined;
$scope.state = 1;
});
$scope.delete = function() {
users.delete(host, name).success(function () {
window.location.href="/admin/users";
})
.error(function (error) {
console.log(error);
});
};
});

View file

@ -4,4 +4,13 @@ angular.module('app').service('users', ['$http', function($http) {
this.getCurrent = function() {
return $http.get('/v1/user');
};
this.get = function(host, login) {
return $http.get('/v1/users/'+host+'/'+login);
};
this.create = function(host, login) {
return $http.post('/v1/users/'+host+'/'+login);
};
this.delete = function(host, login) {
return $http.delete('/v1/users/'+host+'/'+login);
};
}]);

View file

@ -917,6 +917,11 @@ nav div.options .pure-button i {
margin: 10px 0px;
font-size: 22px;
}
#accountpage section h4 small {
opacity: 0.6;
font-size: 16px;
margin-left: 10px;
}
#accountpage section img {
width: 64px;
height: 64px;
@ -928,6 +933,18 @@ nav div.options .pure-button i {
right: 0px;
margin: 20px;
}
#accountpage section .button-error {
color: #FFF;
background: #ca3c3c;
padding: 10px 20px;
float: right;
}
#accountpage section .pure-button-primary {
color: #FFF;
background: #4ab1ce;
padding: 10px 20px;
float: right;
}
#repopage {
width: 100%;
background: #f2f5f8;
@ -1158,3 +1175,18 @@ nav div.options .pure-button i {
white-space: pre-wrap;
overflow: hidden;
}
.pure-form.pure-form-stacked label {
font-size: 14px;
color: #666;
margin-top: 20px;
margin-bottom: 5px;
}
.pure-form.pure-form-stacked label:first-child {
margin-top: 0px;
}
.pure-form.pure-form-stacked input[type="text"],
.pure-form.pure-form-stacked select {
min-width: 300px;
box-shadow: none;
padding: 10px 10px;
}

View file

@ -821,6 +821,11 @@ nav {
h4 {
margin:10px 0px;
font-size:22px;
small {
opacity:0.6;
font-size:16px;
margin-left:10px;
}
}
img {
@ -835,6 +840,20 @@ nav {
right:0px;
margin:20px;
}
.button-error {
color:#FFF;
background: rgb(202, 60, 60);
padding:10px 20px;
float:right;
}
.pure-button-primary {
color:#FFF;
background: @link2;
padding:10px 20px;
float:right;
}
}
}
@ -1030,3 +1049,22 @@ nav {
}
}
}
.pure-form.pure-form-stacked {
label {
font-size:14px;
color:#666;
margin-top:20px;
margin-bottom:5px;
&:first-child {
margin-top:0px;
}
}
input[type="text"],
select {
min-width:300px;
box-shadow:none;
padding:10px 10px;
}
}

File diff suppressed because one or more lines are too long

View file

@ -1,8 +1,8 @@
<div id="userspage">
<nav>
<div class="options">
<a class="pure-button pure-button-primary" href="/admin/users/new">
<i class="fa fa fa-plus"></i> Add User
<a class="pure-button pure-button-primary" href="/admin/users/add">
<i class="fa fa fa-plus"></i> Register User
</a>
</div>

View file

@ -0,0 +1,38 @@
<article id="accountpage">
<nav>
<a href="/admin/users"><span class="fa fa-arrow-left"></span></a>
<a href="/admin/users">users</a>
<span class="separator">/</span>
<a href="/admin/users/add">register</a>
</nav>
<section class="pure-g profile">
<div class="pure-u-1-6">
<div>
<a href="https://gravatar.com/" target="_blank">
<img src="//www.gravatar.com/avatar/00000000000000000000000000000000?d=mm" />
</a>
</div>
</div>
<div class="pure-u-5-6">
<div>
<form class="pure-form pure-form-stacked">
<fieldset>
<label for="host">Service</label>
<select ng-model="host" name="host">
<option value="github.com">GitHub</option>
<option value="enterprise.github.com">GitHub Enterprise</option>
<option value="gitlab.com">GitLab</option>
<option value="bitbucket.org">Bitbucket</option>
<option value="stash.atlassian.com">Stash</option>
</select>
<label for="username">Username</label>
<input type="text" ng-model="name" name="username" placeholder="ex. octocat" />
</fieldset>
</form>
<button ng-click="create()" class="pure-button pure-button-primary">Register Account</button>
</div>
</div>
</section>
</article>

View file

@ -0,0 +1,26 @@
<article id="accountpage">
<nav>
<a href="/admin/users"><span class="fa fa-arrow-left"></span></a>
<a href="/admin/users">users</a>
<span class="separator">/</span>
<a href="/admin/users/{{account.remote}}/{{ account.login }}">edit</a>
</nav>
<section class="pure-g profile">
<div class="pure-u-1-6">
<div>
<a href="https://gravatar.com/" target="_blank">
<img ng-src="{{ account.gravatar | gravatar }}" />
</a>
</div>
</div>
<div class="pure-u-5-6">
<div>
<h4>{{ account.login }} <small>{{ account.remote }}</small></h4>
<span class="fullname">{{ account.name }}</span>
<span class="email">{{ account.email }}</span>
<button ng-click="delete()" class="pure-button button-error">Delete Account</button>
</div>
</div>
</section>
</article>

View file

@ -75,6 +75,7 @@ func (h *LoginHandler) GetLogin(w http.ResponseWriter, r *http.Request) error {
// in case it changed in GitHub
u.Access = login.Access
u.Secret = login.Secret
u.SetEmail(login.Email)
if err := h.users.Update(u); err != nil {
return badRequest{err}
}

View file

@ -6,6 +6,7 @@ import (
"github.com/drone/drone/server/database"
"github.com/drone/drone/server/session"
"github.com/drone/drone/shared/model"
"github.com/gorilla/pat"
)
@ -35,6 +36,80 @@ func (h *UsersHandler) GetUsers(w http.ResponseWriter, r *http.Request) error {
return json.NewEncoder(w).Encode(users)
}
// GetUser gets a user by hostname and login.
// GET /api/users/:host/:login
func (h *UsersHandler) GetUser(w http.ResponseWriter, r *http.Request) error {
remote := r.FormValue(":host")
login := r.FormValue(":login")
// get the user form the session
user := h.sess.User(r)
if user == nil || !user.Admin {
return notAuthorized{}
}
user, err := h.users.FindLogin(remote, login)
if err != nil {
return notFound{err}
}
return json.NewEncoder(w).Encode(user)
}
// PostUser registers a new user account.
// POST /api/users/:host/:login
func (h *UsersHandler) PostUser(w http.ResponseWriter, r *http.Request) error {
remote := r.FormValue(":host")
login := r.FormValue(":login")
// get the user form the session
user := h.sess.User(r)
if user == nil || !user.Admin {
return notAuthorized{}
}
account := model.NewUser(remote, login, "")
if err := h.users.Insert(account); err != nil {
return badRequest{err}
}
return json.NewEncoder(w).Encode(account)
}
// DeleteUser gets a user by hostname and login and deletes
// from the system.
//
// DELETE /api/users/:host/:login
func (h *UsersHandler) DeleteUser(w http.ResponseWriter, r *http.Request) error {
remote := r.FormValue(":host")
login := r.FormValue(":login")
// get the user form the session
user := h.sess.User(r)
if user == nil || !user.Admin {
return notAuthorized{}
}
account, err := h.users.FindLogin(remote, login)
if err != nil {
return notFound{err}
}
// user cannot delete his / her own account
if account.ID == user.ID {
return badRequest{}
}
if err := h.users.Delete(account); err != nil {
return badRequest{err}
}
// return a 200 indicating deletion complete
w.WriteHeader(http.StatusOK)
return nil
}
func (h *UsersHandler) Register(r *pat.Router) {
r.Delete("/v1/users/{host}/{login}", errorHandler(h.DeleteUser))
r.Post("/v1/users/{host}/{login}", errorHandler(h.PostUser))
r.Get("/v1/users/{host}/{login}", errorHandler(h.GetUser))
r.Get("/v1/users", errorHandler(h.GetUsers))
}