mirror of https://github.com/statping/statping
				
				
				
			user update - travis test on dev
							parent
							
								
									3cc63a0f50
								
							
						
					
					
						commit
						268c31418a
					
				| 
						 | 
				
			
			@ -18,7 +18,7 @@ services:
 | 
			
		|||
 | 
			
		||||
env:
 | 
			
		||||
  global:
 | 
			
		||||
     - VERSION=0.29.7
 | 
			
		||||
     - VERSION=0.29.8
 | 
			
		||||
     - DB_HOST=localhost
 | 
			
		||||
     - DB_USER=travis
 | 
			
		||||
     - DB_PASS=
 | 
			
		||||
| 
						 | 
				
			
			@ -65,8 +65,9 @@ before_script:
 | 
			
		|||
  - go get
 | 
			
		||||
 | 
			
		||||
script:
 | 
			
		||||
  - if [[ "$TRAVIS_BRANCH" == "master" ]]; then /bin/bash -c .travis/compile.sh; fi
 | 
			
		||||
  - go test -v -covermode=count -coverprofile=coverage.out && $GOPATH/bin/goveralls -coverprofile=coverage.out -service=travis -repotoken $COVERALLS
 | 
			
		||||
  - /bin/bash -c .travis/compile.sh
 | 
			
		||||
  - go test -v -covermode=count -coverprofile=coverage.out
 | 
			
		||||
  - if [[ "$TRAVIS_BRANCH" == "master" ]]; then $GOPATH/bin/goveralls -coverprofile=coverage.out -service=travis -repotoken $COVERALLS; fi
 | 
			
		||||
 | 
			
		||||
after_success:
 | 
			
		||||
  - if [[ "$TRAVIS_BRANCH" == "master" ]]; then travis_wait 30 docker pull karalabe/xgo-latest; fi
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
FROM alpine:latest
 | 
			
		||||
 | 
			
		||||
ENV VERSION=v0.29.7
 | 
			
		||||
ENV VERSION=v0.29.8
 | 
			
		||||
 | 
			
		||||
RUN apk --no-cache add libstdc++ ca-certificates
 | 
			
		||||
RUN wget -q https://github.com/hunterlong/statup/releases/download/$VERSION/statup-linux-alpine.tar.gz && \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,13 @@ func (u *User) Delete() error {
 | 
			
		|||
	return user.Delete()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (u *User) Update() error {
 | 
			
		||||
	u.CreatedAt = time.Now()
 | 
			
		||||
	col := DbSession.Collection("users")
 | 
			
		||||
	user := col.Find("id", u.Id)
 | 
			
		||||
	return user.Update(u)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (u *User) Create() (int64, error) {
 | 
			
		||||
	u.CreatedAt = time.Now()
 | 
			
		||||
	u.Password = utils.HashPassword(u.Password)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,9 +29,10 @@ func Router() *mux.Router {
 | 
			
		|||
	r.Handle("/service/{id}/delete_failures", http.HandlerFunc(ServicesDeleteFailuresHandler)).Methods("GET")
 | 
			
		||||
	r.Handle("/service/{id}/checkin", http.HandlerFunc(CheckinCreateUpdateHandler)).Methods("POST")
 | 
			
		||||
	r.Handle("/users", http.HandlerFunc(UsersHandler)).Methods("GET")
 | 
			
		||||
	r.Handle("/user/{id}", http.HandlerFunc(UsersHandler)).Methods("GET")
 | 
			
		||||
	r.Handle("/users", http.HandlerFunc(CreateUserHandler)).Methods("POST")
 | 
			
		||||
	r.Handle("/users/{id}/delete", http.HandlerFunc(UsersDeleteHandler)).Methods("GET")
 | 
			
		||||
	r.Handle("/user/{id}", http.HandlerFunc(UsersEditHandler)).Methods("GET")
 | 
			
		||||
	r.Handle("/user/{id}", http.HandlerFunc(UpdateUserHandler)).Methods("POST")
 | 
			
		||||
	r.Handle("/user/{id}/delete", http.HandlerFunc(UsersDeleteHandler)).Methods("GET")
 | 
			
		||||
	r.Handle("/settings", http.HandlerFunc(PluginsHandler)).Methods("GET")
 | 
			
		||||
	r.Handle("/settings", http.HandlerFunc(SaveSettingsHandler)).Methods("POST")
 | 
			
		||||
	r.Handle("/settings/css", http.HandlerFunc(SaveSASSHandler)).Methods("POST")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
package handlers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/gorilla/mux"
 | 
			
		||||
	"github.com/hunterlong/statup/core"
 | 
			
		||||
	"github.com/hunterlong/statup/types"
 | 
			
		||||
| 
						 | 
				
			
			@ -18,13 +19,16 @@ func SessionUser(r *http.Request) *types.User {
 | 
			
		|||
	var user *types.User
 | 
			
		||||
	col := core.DbSession.Collection("users")
 | 
			
		||||
	res := col.Find("id", uuid)
 | 
			
		||||
	res.One(&user)
 | 
			
		||||
	err := res.One(&user)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		utils.Log(3, fmt.Sprintf("cannot fetch user %v", uuid))
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return user
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func UsersHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	auth := IsAuthenticated(r)
 | 
			
		||||
	if !auth {
 | 
			
		||||
	if !IsAuthenticated(r) {
 | 
			
		||||
		http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +36,41 @@ func UsersHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
	ExecuteResponse(w, r, "users.html", users)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func UsersEditHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	if !IsAuthenticated(r) {
 | 
			
		||||
		http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	vars := mux.Vars(r)
 | 
			
		||||
	id, _ := strconv.Atoi(vars["id"])
 | 
			
		||||
	user, _ := core.SelectUser(int64(id))
 | 
			
		||||
	ExecuteResponse(w, r, "user.html", user)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func UpdateUserHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	if !IsAuthenticated(r) {
 | 
			
		||||
		http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	r.ParseForm()
 | 
			
		||||
	vars := mux.Vars(r)
 | 
			
		||||
	id, _ := strconv.Atoi(vars["id"])
 | 
			
		||||
	user, _ := core.SelectUser(int64(id))
 | 
			
		||||
 | 
			
		||||
	user.Username = r.PostForm.Get("username")
 | 
			
		||||
	user.Email = r.PostForm.Get("email")
 | 
			
		||||
	user.Admin = (r.PostForm.Get("admin") == "on")
 | 
			
		||||
	password := r.PostForm.Get("password")
 | 
			
		||||
	if password != "##########" {
 | 
			
		||||
		user.Password = utils.HashPassword(password)
 | 
			
		||||
	}
 | 
			
		||||
	user.Update()
 | 
			
		||||
	users, _ := core.SelectAllUsers()
 | 
			
		||||
	ExecuteResponse(w, r, "users.html", users)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	auth := IsAuthenticated(r)
 | 
			
		||||
	if !auth {
 | 
			
		||||
	if !IsAuthenticated(r) {
 | 
			
		||||
		http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -59,8 +95,7 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func UsersDeleteHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	auth := IsAuthenticated(r)
 | 
			
		||||
	if !auth {
 | 
			
		||||
	if !IsAuthenticated(r) {
 | 
			
		||||
		http.Redirect(w, r, "/", http.StatusSeeOther)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										27
									
								
								main_test.go
								
								
								
								
							
							
						
						
									
										27
									
								
								main_test.go
								
								
								
								
							| 
						 | 
				
			
			@ -64,6 +64,9 @@ func TestRunAll(t *testing.T) {
 | 
			
		|||
		t.Run(dbt+" Create Users", func(t *testing.T) {
 | 
			
		||||
			RunUser_Create(t)
 | 
			
		||||
		})
 | 
			
		||||
		t.Run(dbt+" Update User", func(t *testing.T) {
 | 
			
		||||
			RunUser_Update(t)
 | 
			
		||||
		})
 | 
			
		||||
		t.Run(dbt+" Create Non Unique Users", func(t *testing.T) {
 | 
			
		||||
			t.SkipNow()
 | 
			
		||||
			RunUser_NonUniqueCreate(t)
 | 
			
		||||
| 
						 | 
				
			
			@ -134,6 +137,9 @@ func TestRunAll(t *testing.T) {
 | 
			
		|||
		t.Run(dbt+" HTTP /users", func(t *testing.T) {
 | 
			
		||||
			RunUsersHandler(t)
 | 
			
		||||
		})
 | 
			
		||||
		t.Run(dbt+" HTTP /user/1", func(t *testing.T) {
 | 
			
		||||
			RunUserViewHandler(t)
 | 
			
		||||
		})
 | 
			
		||||
		t.Run(dbt+" HTTP /services", func(t *testing.T) {
 | 
			
		||||
			RunServicesHandler(t)
 | 
			
		||||
		})
 | 
			
		||||
| 
						 | 
				
			
			@ -264,6 +270,7 @@ func RunUser_Create(t *testing.T) {
 | 
			
		|||
		Username: "admin",
 | 
			
		||||
		Password: "admin",
 | 
			
		||||
		Email:    "info@testuser.com",
 | 
			
		||||
		Admin:    true,
 | 
			
		||||
	}
 | 
			
		||||
	id, err := user.Create()
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
| 
						 | 
				
			
			@ -279,6 +286,17 @@ func RunUser_Create(t *testing.T) {
 | 
			
		|||
	assert.Equal(t, int64(2), id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RunUser_Update(t *testing.T) {
 | 
			
		||||
	user, err := core.SelectUser(1)
 | 
			
		||||
	user.Email = "info@updatedemail.com"
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	err = user.Update()
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	updatedUser, err := core.SelectUser(1)
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	assert.Equal(t, "info@updatedemail.com", updatedUser.Email)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RunUser_NonUniqueCreate(t *testing.T) {
 | 
			
		||||
	user := &core.User{
 | 
			
		||||
		Username: "admin",
 | 
			
		||||
| 
						 | 
				
			
			@ -481,6 +499,15 @@ func RunUsersHandler(t *testing.T) {
 | 
			
		|||
	assert.True(t, strings.Contains(rr.Body.String(), "footer"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RunUserViewHandler(t *testing.T) {
 | 
			
		||||
	req, err := http.NewRequest("GET", "/user/1", nil)
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
	rr := httptest.NewRecorder()
 | 
			
		||||
	route.ServeHTTP(rr, req)
 | 
			
		||||
	assert.True(t, strings.Contains(rr.Body.String(), "<title>Statup | Users</title>"))
 | 
			
		||||
	assert.True(t, strings.Contains(rr.Body.String(), "footer"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RunServicesHandler(t *testing.T) {
 | 
			
		||||
	req, err := http.NewRequest("GET", "/services", nil)
 | 
			
		||||
	assert.Nil(t, err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,15 @@ $('form').submit(function() {
 | 
			
		|||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
$(".confirm-btn").on('click', function() {
 | 
			
		||||
    var r = confirm("Are you sure you want to delete?");
 | 
			
		||||
    if (r == true) {
 | 
			
		||||
        return true;
 | 
			
		||||
    } else {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var ranVar = false;
 | 
			
		||||
var ranTheme = false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,64 +22,42 @@
 | 
			
		|||
 | 
			
		||||
    <div class="col-12">
 | 
			
		||||
 | 
			
		||||
        <h3>Users</h3>
 | 
			
		||||
 | 
			
		||||
        <table class="table table-striped">
 | 
			
		||||
            <thead>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <th scope="col">Username</th>
 | 
			
		||||
                <th scope="col"></th>
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
            {{range .}}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td>{{.Username}}</td>
 | 
			
		||||
                <td class="text-right">
 | 
			
		||||
                    <div class="btn-group">
 | 
			
		||||
                        <a href="/users/{{.Id}}/delete" class="btn btn-danger">Delete</a>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            {{end}}
 | 
			
		||||
            </tbody>
 | 
			
		||||
        </table>
 | 
			
		||||
 | 
			
		||||
        <h3>Create User</h3>
 | 
			
		||||
        <form action="/users" method="POST">
 | 
			
		||||
        <h3>User {{.Username}}</h3>
 | 
			
		||||
        <form action="/user/{{.Id}}" method="POST">
 | 
			
		||||
            <div class="form-group row">
 | 
			
		||||
                <label for="username" class="col-sm-4 col-form-label">Username</label>
 | 
			
		||||
                <div class="col-sm-4">
 | 
			
		||||
                    <input type="text" name="username" class="form-control" id="username" placeholder="Username" required>
 | 
			
		||||
                    <input type="text" name="username" class="form-control" value="{{.Username}}" id="username" placeholder="Username" required>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-sm-4">
 | 
			
		||||
                          <span class="switch">
 | 
			
		||||
                            <input type="checkbox" name="admin" class="switch" id="switch-normal">
 | 
			
		||||
                            <label for="switch-normal">Administrator</label>
 | 
			
		||||
                          </span>
 | 
			
		||||
                      <span class="switch">
 | 
			
		||||
                        <input type="checkbox" name="admin" class="switch" id="switch-normal"{{if .Admin}} checked{{end}}>
 | 
			
		||||
                        <label for="switch-normal">Administrator</label>
 | 
			
		||||
                      </span>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="form-group row">
 | 
			
		||||
                <label for="email" class="col-sm-4 col-form-label">Email Address</label>
 | 
			
		||||
                <div class="col-sm-8">
 | 
			
		||||
                    <input type="email" name="email" class="form-control" id="email" placeholder="user@domain.com" required>
 | 
			
		||||
                    <input type="email" name="email" class="form-control" id="email" value="{{.Email}}" placeholder="user@domain.com" required>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="form-group row">
 | 
			
		||||
                <label for="password" class="col-sm-4 col-form-label">Password</label>
 | 
			
		||||
                <div class="col-sm-8">
 | 
			
		||||
                    <input type="password" name="password" class="form-control" id="password" placeholder="Password" required>
 | 
			
		||||
                    <input type="password" name="password" class="form-control" id="password" value="##########" placeholder="Password" required>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="form-group row">
 | 
			
		||||
                <label for="password_confirm" class="col-sm-4 col-form-label">Confirm Password</label>
 | 
			
		||||
                <div class="col-sm-8">
 | 
			
		||||
                    <input type="password" name="password_confirm" class="form-control" id="password_confirm" placeholder="Confirm Password" required>
 | 
			
		||||
                    <input type="password" name="password_confirm" class="form-control" id="password_confirm" value="##########" placeholder="Confirm Password" required>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="form-group row">
 | 
			
		||||
                <div class="col-sm-12">
 | 
			
		||||
                    <button type="submit" class="btn btn-primary btn-block">Create User</button>
 | 
			
		||||
                    <input type="hidden" name="user_id" value="{{.Id}}">
 | 
			
		||||
                    <button type="submit" class="btn btn-primary btn-block">Update User</button>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </form>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,9 +35,10 @@
 | 
			
		|||
                {{range .}}
 | 
			
		||||
                <tr>
 | 
			
		||||
                    <td>{{.Username}}</td>
 | 
			
		||||
                    <td class="text-right">
 | 
			
		||||
                    <td class="text-right" id="user_{{.Id}}">
 | 
			
		||||
                        <div class="btn-group">
 | 
			
		||||
                            <a href="/users/{{.Id}}/delete" class="btn btn-danger">Delete</a>
 | 
			
		||||
                            <a href="/user/{{.Id}}" class="btn btn-primary">Edit</a>
 | 
			
		||||
                            <a href="/user/{{.Id}}/delete" class="btn btn-danger confirm-btn" data-id="user_{{.Id}}">Delete</a>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue