package system import ( "net/http" "strconv" "strings" "time" "github.com/jinzhu/gorm" "goji.io" "goji.io/pat" libapi "dev.sum7.eu/sum7/warehost/lib/api" liblog "dev.sum7.eu/sum7/warehost/lib/log" libpassword "dev.sum7.eu/sum7/warehost/lib/password" libsession "dev.sum7.eu/sum7/warehost/lib/session" ) //MODULNAME to get global name for the modul const MODULNAME = "system" var dbconnection *gorm.DB var log *liblog.ModulLog // BindAPI sets the routes to the api functions func BindAPI(db *gorm.DB, router *goji.Mux, prefix string) { dbconnection = db log = liblog.NewModulLog(MODULNAME) router.HandleFunc(pat.Get(prefix+"/status"), libapi.SessionHandler(status)) router.HandleFunc(pat.Post(prefix+"/login"), libapi.SessionHandler(login)) router.HandleFunc(pat.Get(prefix+"/logout"), libapi.SessionHandler(LoginHandler(logout))) router.HandleFunc(pat.Post(prefix+"/password"), libapi.SessionHandler(LoginHandler(password))) router.HandleFunc(pat.Get(prefix+"/delete"), libapi.SessionHandler(LoginHandler(delete))) router.HandleFunc(pat.Get(prefix+"/invite"), libapi.SessionHandler(LoginHandler(inviteList))) router.HandleFunc(pat.Post(prefix+"/invite"), libapi.SessionHandler(LoginHandler(inviteAdd))) router.HandleFunc(pat.Get(prefix+"/user"), libapi.SessionHandler(LoginHandler(loginList))) router.HandleFunc(pat.Post(prefix+"/user"), libapi.SessionHandler(LoginHandler(loginAdd))) router.HandleFunc(pat.Patch(prefix+"/user/:id"), libapi.SessionHandler(LoginHandler(loginEdit))) router.HandleFunc(pat.Delete(prefix+"/user/:id"), libapi.SessionHandler(LoginHandler(loginDelete))) router.HandleFunc(pat.Get(prefix+"/invitor"), libapi.SessionHandler(LoginHandler(invitor))) router.HandleFunc(pat.Patch(prefix+"/invitor"), libapi.SessionHandler(LoginHandler(invitorAdminToggle))) } // Status to get Login and Server status func status(w http.ResponseWriter, r *http.Request) { logger := log.GetLog(r, "status") var result int64 dbconnection.Model(&Login{}).Count(&result) if result > 0 { libapi.JSONWrite(w, r, true, nil) return } logger.Info("done") libapi.JSONWrite(w, r, false, nil) } // Logout current user func logout(w http.ResponseWriter, r *http.Request) { ctx := r.Context() sess := ctx.Value("session").(libsession.Session) libsession.SessionDestroy(w, r) logger := log.GetLog(r, "logout") if login := sess.Get("login"); login != nil { logger = logger.WithField("user", login.(*Login).Username) } sess.Delete("login") sess.Delete("profil") logger.Info("done") libapi.JSONWrite(w, r, true, nil) } // Login of system func login(w http.ResponseWriter, r *http.Request) { ctx := r.Context() sess := ctx.Value("session").(libsession.Session) logger := log.GetLog(r, "login") var requestlogin RequestLogin returnerr := libapi.JSONDecoder(w, r, logger, &requestlogin) if returnerr != nil { libapi.JSONWrite(w, r, false, returnerr) return } logger = logger.WithField("user", requestlogin.Username) var login = Login{Username: requestlogin.Username} dbconnection.Where("mail = ?", requestlogin.Username).First(&login) if login.ID <= 0 { logger.Warn("user not found") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Fields: []string{"username"}, Message: "User not Found"}) return } if login.Active { output, _ := libpassword.Validate(login.Password, requestlogin.Password) if output { dbconnection.Model(&login).Update("LastLoginAt", time.Now()) sess.Set("login", &login) logger.Info("done") libapi.JSONWrite(w, r, true, nil) return } logger.Warn("wrong password") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Fields: []string{"password"}, Message: "Wrong Password"}) return } logger.Warn("not active") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Fields: []string{"active"}, Message: "Not a active User"}) return } //Password to change the password func password(w http.ResponseWriter, r *http.Request) { ctx := r.Context() sess := ctx.Value("session").(libsession.Session) login := ctx.Value("login").(*Login) logger := log.GetLog(r, "password") var changePasswordRequest ChangePasswordRequest returnerr := libapi.JSONDecoder(w, r, logger, &changePasswordRequest) if returnerr != nil { libapi.JSONWrite(w, r, false, returnerr) return } output, _ := libpassword.Validate(login.Password, changePasswordRequest.CurrentPassword) if !output { logger.Warn("wrong current password") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Fields: []string{"currentpassword"}, Message: "Wrong CurrentPassword"}) return } if len(changePasswordRequest.NewPassword) < MINPASSWORDLENTH { logger.Warn("wrong new password") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Fields: []string{"newpassword"}, Message: "Wrong NewPassword"}) return } login.Password = libpassword.NewHash(changePasswordRequest.NewPassword) if err := dbconnection.Save(login).Error; err != nil { logger.Warn("error save new password to database") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error save new password"}) return } sess.Set("login", login) logger.Info("done") libapi.JSONWrite(w, r, true, nil) } //Delete of login on warehost func delete(w http.ResponseWriter, r *http.Request) { ctx := r.Context() sess := ctx.Value("session").(libsession.Session) login := ctx.Value("login").(*Login) logger := log.GetLog(r, "delete") sess.Delete("login") if err := dbconnection.Unscoped().Delete(login).Error; err != nil { logger.Warn("error detete login") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error delete login"}) return } logger.Warn("done") libapi.JSONWrite(w, r, true, nil) } // InviteList list all of your invites func inviteList(w http.ResponseWriter, r *http.Request) { ctx := r.Context() login := ctx.Value("login").(*Login) logger := log.GetLog(r, "invitelist") if err := dbconnection.Model(login).Preload("Invites.Invited").First(login).Error; err != nil { logger.Warn("error load own invites") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Could not load invites!"}) return } logger.Info("done") libapi.JSONWrite(w, r, login.Invites, nil) } // InviteAdd invite a new user to warehost func inviteAdd(w http.ResponseWriter, r *http.Request) { ctx := r.Context() login := ctx.Value("login").(*Login) logger := log.GetLog(r, "inviteadd") var newLogin RequestLogin returnerr := libapi.JSONDecoder(w, r, logger, &newLogin) if returnerr != nil { libapi.JSONWrite(w, r, false, returnerr) return } invite := &Invite{ Login: *login, Invited: Login{ Username: strings.ToLower(newLogin.Username), Password: libpassword.NewHash(newLogin.Password), Active: true, }, } if err := dbconnection.Create(invite).Error; err != nil { logger.Warn("error create invite") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Username exists already"}) return } logger.Info("done") libapi.JSONWrite(w, r, true, nil) } // LoginList list all users in system func loginList(w http.ResponseWriter, r *http.Request) { ctx := r.Context() login := ctx.Value("login").(*Login) logger := log.GetLog(r, "loginlist") var logins []Login selectfield := "ID, mail" if login.Superadmin { selectfield = "ID, mail, superadmin, active" } if err := dbconnection.Select(selectfield).Find(&logins).Error; err != nil { logger.Warn("sql list login") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error during list login"}) return } logger.Info("done") libapi.JSONWrite(w, r, logins, nil) } // LoginAdd add a new Login func loginAdd(w http.ResponseWriter, r *http.Request) { ctx := r.Context() login := ctx.Value("login").(*Login) logger := log.GetLog(r, "loginadd") if !login.Superadmin { logger.Error("no superadmin") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error no permission to edit this invite"}) return } var newLogin RequestLogin returnerr := libapi.JSONDecoder(w, r, logger, &newLogin) if returnerr != nil { libapi.JSONWrite(w, r, false, returnerr) return } loginObj := Login{ Username: strings.ToLower(newLogin.Username), Password: libpassword.NewHash(newLogin.Password), Active: true, } if err := dbconnection.Create(loginObj).Error; err != nil { logger.Warn("error create login") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Username exists already"}) return } logger.Info("done") libapi.JSONWrite(w, r, true, nil) } // LoginEdit edit a login by invite or superadmin func loginEdit(w http.ResponseWriter, r *http.Request) { ctx := r.Context() login := ctx.Value("login").(*Login) logger := log.GetLog(r, "loginedit") id, err := strconv.ParseInt(pat.Param(r, "id"), 10, 64) if err != nil { logger.Warn("invalid userinput, no integer") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error invalid input"}) return } logger = logger.WithField("id", id) var invitedLogin = Login{ID: id} var changeLogin RequestLogin returnerr := libapi.JSONDecoder(w, r, logger, &changeLogin) if returnerr != nil { libapi.JSONWrite(w, r, false, returnerr) return } dbconnection.Where("id = ?", invitedLogin.ID).First(&invitedLogin) invite := invitedLogin.GetInvitedby(dbconnection) if !login.Superadmin && !invite.Admin && invitedLogin.CreateAt.Before(invitedLogin.LastLoginAt) { logger.Warn("no permission") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error no permission to edit this login"}) return } if len(changeLogin.Password) > 0 { invitedLogin.Password = libpassword.NewHash(changeLogin.Password) } if login.Superadmin { invitedLogin.Username = changeLogin.Username invitedLogin.Superadmin = changeLogin.Superadmin invitedLogin.Active = changeLogin.Active } if err := dbconnection.Save(invitedLogin).Error; err != nil { logger.Warn("sql edit login") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error during edit login"}) return } logger.Info("done") libapi.JSONWrite(w, r, true, nil) } // LoginDelete delete a login by invite or superadmin func loginDelete(w http.ResponseWriter, r *http.Request) { ctx := r.Context() login := ctx.Value("login").(*Login) logger := log.GetLog(r, "logindelete") id, err := strconv.ParseInt(pat.Param(r, "id"), 10, 64) if err != nil { logger.Warn("invalid userinput, no integer") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error invalid input"}) return } logger = logger.WithField("id", id) var invitedLogin = Login{ID: id} dbconnection.Where("id = ?", invitedLogin.ID).First(&invitedLogin) invite := invitedLogin.GetInvitedby(dbconnection) if !login.Superadmin && !invite.Admin && invitedLogin.CreateAt.Before(invitedLogin.LastLoginAt) { logger.Warn("no permission") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error no permission to delete this login"}) return } if err := dbconnection.Unscoped().Delete(invitedLogin).Error; err != nil { logger.Warn("sql detete login") libapi.JSONWrite(w, r, false, &libapi.ErrorResult{Message: "Error during delete login"}) return } logger.Info("done") libapi.JSONWrite(w, r, true, nil) } // Invitor get Invite of current login func invitor(w http.ResponseWriter, r *http.Request) { ctx := r.Context() login := ctx.Value("login").(*Login) logger := log.GetLog(r, "invitor") invite := login.GetInvitedby(dbconnection) logger.Info("done") libapi.JSONWrite(w, r, invite, nil) } // InvitorAdminToggle toggle admin of current login func invitorAdminToggle(w http.ResponseWriter, r *http.Request) { ctx := r.Context() login := ctx.Value("login").(*Login) logger := log.GetLog(r, "invitoradmintoggle") invite := login.GetInvitedby(dbconnection) invite.Admin = !invite.Admin dbconnection.Model(invite).Save(&invite) logger.Info("done") libapi.JSONWrite(w, r, true, nil) }