sum7/warehost
sum7
/
warehost
Archived
1
0
Fork 0

improve invite (with all function)

This commit is contained in:
Martin Geno 2016-08-24 23:02:25 +02:00
parent cd8bff38ab
commit 1cf3dfd47a
5 changed files with 144 additions and 52 deletions

View File

@ -2,13 +2,14 @@ package libPassword
import "fmt" import "fmt"
func main(){ func main() {
password_str := "root" password_str := "root"
x,err :=Validate("pbkdf2_sha1$10000$a5viM+Paz3o=$orD4shu1Ss+1wPAhAt8hkZ/fH7Y=",password_str); if x { x, err := Validate("pbkdf2_sha1$10000$a5viM+Paz3o=$orD4shu1Ss+1wPAhAt8hkZ/fH7Y=", password_str)
if x {
fmt.Println("Valide") fmt.Println("Valide")
if err { if err {
fmt.Print("Deprecated,replace with: ") fmt.Print("Deprecated,replace with: ")
fmt.Println(NewHesh(password_str)) fmt.Println(NewHash(password_str))
} }
} }
} }

View File

@ -12,32 +12,33 @@ import "fmt"
import "strings" import "strings"
const ( const (
salt_length = 8 salt_length = 8
hesh_length = 20 hash_length = 20
interations = 10000 interations = 10000
hashfunc string = "sha256" hashfunc string = "sha256"
) )
var hashlib = map[string] func()hash.Hash{
"sha1":sha1.New,
"sha256":sha256.New,
"sha512":sha512.New,
}
func Validate(hash,password string)(output,replace bool){ var hashlib = map[string]func() hash.Hash{
parts := strings.Split(hash,"$") "sha1": sha1.New,
"sha256": sha256.New,
"sha512": sha512.New,
}
func Validate(hash, password string) (output, replace bool) {
parts := strings.Split(hash, "$")
if len(parts) == 3 { if len(parts) == 3 {
return false,false return false, false
} }
cur_iter,err := strconv.Atoi(parts[1]) cur_iter, err := strconv.Atoi(parts[1])
if err != nil { if err != nil {
return false,false return false, false
} }
hashfunc_c := strings.Split(parts[0],"_")[1] hashfunc_c := strings.Split(parts[0], "_")[1]
replace = (hashfunc_c!=hashfunc) replace = (hashfunc_c != hashfunc)
dk := pbkdf2.Key([]byte(password), []byte(parts[2]), cur_iter, len(parts[3])-8, hashlib[hashfunc_c]) dk := pbkdf2.Key([]byte(password), []byte(parts[2]), cur_iter, len(parts[3])-8, hashlib[hashfunc_c])
x := fmt.Sprintf("pbkdf2_%s$%s$%s$%s",hashfunc_c,parts[1],parts[2],base64.StdEncoding.EncodeToString(dk)) x := fmt.Sprintf("pbkdf2_%s$%s$%s$%s", hashfunc_c, parts[1], parts[2], base64.StdEncoding.EncodeToString(dk))
output = (x==hash) output = (x == hash)
return return
} }
func GenerateRandomString(n int) (string, error) { func GenerateRandomString(n int) (string, error) {
@ -48,8 +49,8 @@ func GenerateRandomString(n int) (string, error) {
} }
return base64.URLEncoding.EncodeToString(b), nil return base64.URLEncoding.EncodeToString(b), nil
} }
func NewHesh(password string)string{ func NewHash(password string) string {
salt,_ := GenerateRandomString(salt_length) salt, _ := GenerateRandomString(salt_length)
dk := pbkdf2.Key([]byte(password), []byte(salt), interations, hesh_length, hashlib[hashfunc]) dk := pbkdf2.Key([]byte(password), []byte(salt), interations, hash_length, hashlib[hashfunc])
return fmt.Sprintf("pbkdf2_%s$%d$%s$%s",hashfunc,interations,salt,base64.StdEncoding.EncodeToString(dk)) return fmt.Sprintf("pbkdf2_%s$%d$%s$%s", hashfunc, interations, salt, base64.StdEncoding.EncodeToString(dk))
} }

View File

@ -62,6 +62,7 @@ func main() {
c := cors.New(cors.Options{ c := cors.New(cors.Options{
AllowedOrigins: []string{config.API.AllowedOrigins}, AllowedOrigins: []string{config.API.AllowedOrigins},
AllowCredentials: true, AllowCredentials: true,
AllowedMethods: []string{"GET", "POST", "PUT", "DELETE"},
}) })
handler := c.Handler(router) handler := c.Handler(router)
// Start server // Start server

View File

@ -3,7 +3,9 @@ package system
import ( import (
"encoding/json" "encoding/json"
"net/http" "net/http"
"strconv"
"strings" "strings"
"time"
"github.com/astaxie/session" "github.com/astaxie/session"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
@ -41,8 +43,10 @@ func NewAPI(config *libconfig.Config, sessions *session.Manager, dbconnection *g
router.GET(prefix+"/delete", LoginHandler(api.Delete, sessions)) router.GET(prefix+"/delete", LoginHandler(api.Delete, sessions))
router.GET(prefix+"/invite", LoginHandler(api.InviteList, sessions)) router.GET(prefix+"/invite", LoginHandler(api.InviteList, sessions))
router.POST(prefix+"/invite", LoginHandler(api.InviteAdd, sessions)) router.POST(prefix+"/invite", LoginHandler(api.InviteAdd, sessions))
router.PUT(prefix+"/invite", LoginHandler(api.InviteEdit, sessions)) router.PUT(prefix+"/invite/:id", LoginHandler(api.LoginEdit, sessions))
router.DELETE(prefix+"/invite", LoginHandler(api.InviteDelete, sessions)) router.DELETE(prefix+"/invite/:id", LoginHandler(api.LoginDelete, sessions))
router.GET(prefix+"/invitor", LoginHandler(api.Invitor, sessions))
router.PUT(prefix+"/invitor", LoginHandler(api.InvitorAdminToggle, sessions))
} }
// Status to get Login and Server status // Status to get Login and Server status
@ -74,6 +78,7 @@ func (api *API) Logout(w http.ResponseWriter, r *http.Request, _ httprouter.Para
// Login of system // Login of system
func (api *API) Login(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session) (returndata interface{}, returnerr *libapi.ErrorResult) { func (api *API) Login(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session) (returndata interface{}, returnerr *libapi.ErrorResult) {
returndata = false
logger := api.log.GetLog(r, "login") logger := api.log.GetLog(r, "login")
var requestlogin RequestLogin var requestlogin RequestLogin
err := json.NewDecoder(r.Body).Decode(&requestlogin) err := json.NewDecoder(r.Body).Decode(&requestlogin)
@ -83,7 +88,6 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ httprouter.Param
returnerr = &libapi.ErrorResult{ returnerr = &libapi.ErrorResult{
Message: "Internal Request Error", Message: "Internal Request Error",
} }
returndata = false
return return
} }
logger = logger.WithField("user", requestlogin.Username) logger = logger.WithField("user", requestlogin.Username)
@ -92,14 +96,14 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ httprouter.Param
if login.ID <= 0 { if login.ID <= 0 {
logger.Warn("user not found") logger.Warn("user not found")
returnerr = &libapi.ErrorResult{Fields: []string{"username"}, Message: "User not Found"} returnerr = &libapi.ErrorResult{Fields: []string{"username"}, Message: "User not Found"}
returndata = false
return return
} }
returndata = false
if login.Active { if login.Active {
output, _ := libpassword.Validate(login.Password, requestlogin.Password) output, _ := libpassword.Validate(login.Password, requestlogin.Password)
if output { if output {
returndata = true returndata = true
login.LastLoginAt = time.Now()
api.dbconnection.Save(&login)
sess.Set("login", login) sess.Set("login", login)
logger.Info("logged in") logger.Info("logged in")
} else { } else {
@ -116,8 +120,8 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ httprouter.Param
//Password to change the password //Password to change the password
func (api *API) Password(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) { func (api *API) Password(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) {
logger := api.log.GetLog(r, "password")
returndata = false returndata = false
logger := api.log.GetLog(r, "password")
var changePasswordRequest ChangePasswordRequest var changePasswordRequest ChangePasswordRequest
err := json.NewDecoder(r.Body).Decode(&changePasswordRequest) err := json.NewDecoder(r.Body).Decode(&changePasswordRequest)
@ -139,28 +143,27 @@ func (api *API) Password(w http.ResponseWriter, r *http.Request, _ httprouter.Pa
returnerr = &libapi.ErrorResult{Fields: []string{"newpassword"}, Message: "Wrong NewPassword"} returnerr = &libapi.ErrorResult{Fields: []string{"newpassword"}, Message: "Wrong NewPassword"}
return return
} }
login.Password = libpassword.NewHesh(changePasswordRequest.NewPassword) login.Password = libpassword.NewHash(changePasswordRequest.NewPassword)
if err := api.dbconnection.Save(login).Error; err != nil { if err := api.dbconnection.Save(login).Error; err != nil {
logger.Warn("error save new password to database") logger.Warn("error save new password to database")
returnerr = &libapi.ErrorResult{Message: "Error save new password"} returnerr = &libapi.ErrorResult{Message: "Error save new password"}
returndata = false
return return
} }
sess.Set("login", *login) sess.Set("login", *login)
returndata = true
logger.Info("works") logger.Info("works")
returndata = true
return return
} }
//Delete of login on warehost //Delete of login on warehost
func (api *API) Delete(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) { func (api *API) Delete(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) {
returndata = false
logger := api.log.GetLog(r, "delete") logger := api.log.GetLog(r, "delete")
logger.Warn("login delete") logger.Warn("login delete")
sess.Delete("login") sess.Delete("login")
if err := api.dbconnection.Unscoped().Delete(login).Error; err != nil { if err := api.dbconnection.Unscoped().Delete(login).Error; err != nil {
logger.Warn("error detete login") logger.Warn("error detete login")
returnerr = &libapi.ErrorResult{Message: "Error delete login"} returnerr = &libapi.ErrorResult{Message: "Error delete login"}
returndata = false
return return
} }
returndata = true returndata = true
@ -169,12 +172,12 @@ func (api *API) Delete(w http.ResponseWriter, r *http.Request, _ httprouter.Para
// InviteList list all of your invites // InviteList list all of your invites
func (api *API) InviteList(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) { func (api *API) InviteList(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) {
returndata = false
logger := api.log.GetLog(r, "invitelist") logger := api.log.GetLog(r, "invitelist")
logger.Info("list invites") logger.Info("list invites")
if err := api.dbconnection.Model(login).Preload("Invites.Invited").First(login).Error; err != nil { if err := api.dbconnection.Model(login).Preload("Invites.Invited").First(login).Error; err != nil {
logger.Warn("error load own invites") logger.Warn("error load own invites")
returnerr = &libapi.ErrorResult{Message: "Could not load invites!"} returnerr = &libapi.ErrorResult{Message: "Could not load invites!"}
returndata = false
return return
} }
returndata = login.Invites returndata = login.Invites
@ -183,8 +186,8 @@ func (api *API) InviteList(w http.ResponseWriter, r *http.Request, _ httprouter.
// InviteAdd invite a new user to warehost // InviteAdd invite a new user to warehost
func (api *API) InviteAdd(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) { func (api *API) InviteAdd(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) {
logger := api.log.GetLog(r, "inviteadd")
returndata = false returndata = false
logger := api.log.GetLog(r, "inviteadd")
var newLogin RequestLogin var newLogin RequestLogin
err := json.NewDecoder(r.Body).Decode(&newLogin) err := json.NewDecoder(r.Body).Decode(&newLogin)
if err != nil { if err != nil {
@ -197,14 +200,13 @@ func (api *API) InviteAdd(w http.ResponseWriter, r *http.Request, _ httprouter.P
Login: *login, Login: *login,
Invited: Login{ Invited: Login{
Username: strings.ToLower(newLogin.Username), Username: strings.ToLower(newLogin.Username),
Password: libpassword.NewHesh(newLogin.Password), Password: libpassword.NewHash(newLogin.Password),
Active: true, Active: true,
}, },
} }
if err := api.dbconnection.Create(invite).Error; err != nil { if err := api.dbconnection.Create(invite).Error; err != nil {
logger.Warn("error create invite") logger.Warn("error create invite")
returnerr = &libapi.ErrorResult{Message: "Username exists already"} returnerr = &libapi.ErrorResult{Message: "Username exists already"}
returndata = false
return return
} }
logger.Info("invite") logger.Info("invite")
@ -212,18 +214,99 @@ func (api *API) InviteAdd(w http.ResponseWriter, r *http.Request, _ httprouter.P
return return
} }
// InviteEdit edit a invite // LoginEdit edit a login by invite or superadmin
func (api *API) InviteEdit(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) { func (api *API) LoginEdit(w http.ResponseWriter, r *http.Request, ps httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) {
logger := api.log.GetLog(r, "inviteedit")
logger.Warn("not implemented")
returndata = false returndata = false
logger := api.log.GetLog(r, "loginedit")
tmpID64, err := strconv.ParseUint(ps.ByName("id"), 10, 32)
id := uint(tmpID64)
if err != nil {
returnerr = &libapi.ErrorResult{Message: "Error invalid input"}
logger.Warn("invalid userinput, no integer")
return
}
logger = logger.WithField("id", id)
var invitedLogin = Login{ID: id}
var changeLogin RequestLogin
err = json.NewDecoder(r.Body).Decode(&changeLogin)
if err != nil {
logger.Error("fetch request")
http.Error(w, err.Error(), http.StatusInternalServerError)
returnerr = &libapi.ErrorResult{Message: "Internal Request Error"}
return
}
api.dbconnection.Where("id = ?", invitedLogin.ID).First(&invitedLogin)
invite := login.GetInvitedby(api.dbconnection)
if !login.Superadmin && !invite.Admin && invitedLogin.CreateAt.Before(invitedLogin.LastLoginAt) {
logger.Warn("no permission")
returnerr = &libapi.ErrorResult{Message: "Error no permission to edit this invite"}
return
}
if len(changeLogin.Password) > 0 {
invitedLogin.Password = libpassword.NewHash(changeLogin.Password)
}
if login.Superadmin {
invitedLogin.Username = changeLogin.Username
}
if err := api.dbconnection.Save(invitedLogin).Error; err != nil {
logger.Warn("sql edit login")
returnerr = &libapi.ErrorResult{Message: "Error during edit login"}
return
}
logger.Info("login edit")
returndata = true
return return
} }
// InviteDelete delete a invite // LoginDelete delete a login by invite or superadmin
func (api *API) InviteDelete(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) { func (api *API) LoginDelete(w http.ResponseWriter, r *http.Request, ps httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) {
logger := api.log.GetLog(r, "invitedelete")
logger.Warn("not implemented")
returndata = false returndata = false
logger := api.log.GetLog(r, "logindelete")
tmpID64, err := strconv.ParseUint(ps.ByName("id"), 10, 32)
id := uint(tmpID64)
if err != nil {
returnerr = &libapi.ErrorResult{Message: "Error invalid input"}
logger.Warn("invalid userinput, no integer")
return
}
logger = logger.WithField("id", id)
var invitedLogin = Login{ID: id}
api.dbconnection.Where("id = ?", invitedLogin.ID).First(&invitedLogin)
invite := login.GetInvitedby(api.dbconnection)
if !login.Superadmin && !invite.Admin && invitedLogin.CreateAt.Before(invitedLogin.LastLoginAt) {
logger.Warn("no permission")
returnerr = &libapi.ErrorResult{Message: "Error no permission to delete this invite"}
return
}
if err := api.dbconnection.Unscoped().Delete(invitedLogin).Error; err != nil {
logger.Warn("sql detete login")
returnerr = &libapi.ErrorResult{Message: "Error during delete login"}
return
}
logger.Info("login deleted")
returndata = true
return
}
// Invitor get Invite of current login
func (api *API) Invitor(w http.ResponseWriter, r *http.Request, ps httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) {
returndata = false
logger := api.log.GetLog(r, "invitor")
invite := login.GetInvitedby(api.dbconnection)
logger.Info("show invitor")
returndata = invite
return
}
// InvitorAdmin toggle admin of current login
func (api *API) InvitorAdminToggle(w http.ResponseWriter, r *http.Request, ps httprouter.Params, sess session.Session, login *Login) (returndata interface{}, returnerr *libapi.ErrorResult) {
returndata = false
logger := api.log.GetLog(r, "invitoradmintoggle")
invite := login.GetInvitedby(api.dbconnection)
invite.Admin = !invite.Admin
api.dbconnection.Model(invite).Save(&invite)
logger.Info("toggle saved")
returndata = true
return return
} }

View File

@ -42,18 +42,24 @@ type Login struct {
Superadmin bool `gorm:"default:'false';column:superadmin" json:"superadmin"` Superadmin bool `gorm:"default:'false';column:superadmin" json:"superadmin"`
CreateAt time.Time `sql:"default:current_timestamp" gorm:"column:createat" json:"createat"` CreateAt time.Time `sql:"default:current_timestamp" gorm:"column:createat" json:"createat"`
LastLoginAt time.Time `gorm:"column:lastloginat" json:"lastloginat"` LastLoginAt time.Time `gorm:"column:lastloginat" json:"lastloginat"`
Invites []Invite `gorm:"foreignkey:Login"` Invites []Invite `gorm:"foreignkey:Login" json:"invites"`
} }
// Login found // Login found
type Invite struct { type Invite struct {
LoginID uint `sql:"type:bigint REFERENCES login(id) ON UPDATE CASCADE ON DELETE CASCADE;column:login"` LoginID uint `sql:"type:bigint REFERENCES login(id) ON UPDATE CASCADE ON DELETE CASCADE;column:login;primary_key"`
Login Login `gorm:"column:login" json:"login"` Login Login `gorm:"column:login" json:"login"`
InvitedID uint `sql:"type:bigint REFERENCES login(id) ON UPDATE CASCADE ON DELETE CASCADE;column:invited"` InvitedID uint `sql:"type:bigint REFERENCES login(id) ON UPDATE CASCADE ON DELETE CASCADE;column:invited;primary_key"`
Invited Login `gorm:"column:invited" json:"invited"` Invited Login `gorm:"column:invited" json:"invited"`
Admin bool `sql:"default:'false'" json:"admin"` Admin bool `sql:"default:'false'" json:"admin"`
} }
func (l *Login) GetInvitedby(dbconnection *gorm.DB) (invited Invite) {
invited = Invite{InvitedID: l.ID}
dbconnection.Where("invited = ?", invited.InvitedID).First(&invited)
return
}
// SyncModels to verify the database schema // SyncModels to verify the database schema
func SyncModels(dbconnection *gorm.DB) { func SyncModels(dbconnection *gorm.DB) {
dbconnection.AutoMigrate(&Login{}, &Invite{}) dbconnection.AutoMigrate(&Login{}, &Invite{})
@ -65,12 +71,12 @@ func SyncModels(dbconnection *gorm.DB) {
Username: "root", Username: "root",
Active: true, Active: true,
Superadmin: true, Superadmin: true,
Password: libpassword.NewHesh("root"), Password: libpassword.NewHash("root"),
} }
dbconnection.Create(login) dbconnection.Create(login)
log.Log.Error("have to create \"login\"") log.Log.Error("have to create \"login\"")
} else { } else {
log.Log.Info("Conection to \"login\" works") log.Log.Info("Connection to \"login\" works")
} }
} }