[web] permissions added
This commit is contained in:
parent
b3b7222187
commit
33f7f52f6f
|
@ -7,7 +7,7 @@ log:
|
||||||
path: test.log
|
path: test.log
|
||||||
webroot: ./webroot/build
|
webroot: ./webroot/build
|
||||||
database: "host=localhost user=warehost dbname=warehost password=hallo sslmode=disable"
|
database: "host=localhost user=warehost dbname=warehost password=hallo sslmode=disable"
|
||||||
databasedebug: true
|
databasedebug: false
|
||||||
modules:
|
modules:
|
||||||
web:
|
web:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
|
@ -37,6 +37,9 @@ func NewAPI(config *libconfig.Config, sessions *session.Manager, dbconnection *g
|
||||||
router.POST(prefix+"/website", libsystem.LoginHandler(api.WebsiteAdd, sessions))
|
router.POST(prefix+"/website", libsystem.LoginHandler(api.WebsiteAdd, sessions))
|
||||||
router.PUT(prefix+"/website/:websiteid", InvolveWebsiteHandler(api.WebsiteEdit, sessions, dbconnection))
|
router.PUT(prefix+"/website/:websiteid", InvolveWebsiteHandler(api.WebsiteEdit, sessions, dbconnection))
|
||||||
router.DELETE(prefix+"/website/:websiteid", InvolveWebsiteHandler(api.WebsiteDelete, sessions, dbconnection))
|
router.DELETE(prefix+"/website/:websiteid", InvolveWebsiteHandler(api.WebsiteDelete, sessions, dbconnection))
|
||||||
|
router.GET(prefix+"/website/:websiteid/permission", InvolveWebsiteHandler(api.PermissionList, sessions, dbconnection))
|
||||||
|
router.POST(prefix+"/website/:websiteid/permission/:loginid", InvolveWebsiteHandler(api.PermissionAdd, sessions, dbconnection))
|
||||||
|
router.DELETE(prefix+"/website/:websiteid/permission/:loginid", InvolveWebsiteHandler(api.PermissionDelete, sessions, dbconnection))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Involve to get Website where loggend in user has privilegs
|
// Involve to get Website where loggend in user has privilegs
|
||||||
|
@ -45,7 +48,7 @@ func (api *API) Involve(w http.ResponseWriter, r *http.Request, _ httprouter.Par
|
||||||
logger := api.log.GetLog(r, "involve")
|
logger := api.log.GetLog(r, "involve")
|
||||||
var involved []*Manager
|
var involved []*Manager
|
||||||
api.dbconnection.Where("login = ?", login.ID).Preload("Website").Find(&involved)
|
api.dbconnection.Where("login = ?", login.ID).Preload("Website").Find(&involved)
|
||||||
logger.Info("okay")
|
logger.Info("done")
|
||||||
returndata = involved
|
returndata = involved
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -81,7 +84,7 @@ func (api *API) WebsiteAdd(w http.ResponseWriter, r *http.Request, _ httprouter.
|
||||||
|
|
||||||
tx.Commit()
|
tx.Commit()
|
||||||
returndata = true
|
returndata = true
|
||||||
logger.Info("okay")
|
logger.Info("done")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +107,7 @@ func (api *API) WebsiteEdit(w http.ResponseWriter, r *http.Request, _ httprouter
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
returndata = true
|
returndata = true
|
||||||
logger.Warn("okay")
|
logger.Info("done")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,6 +124,6 @@ func (api *API) WebsiteDelete(w http.ResponseWriter, r *http.Request, _ httprout
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
returndata = true
|
returndata = true
|
||||||
logger.Warn("okay")
|
logger.Info("done")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/astaxie/session"
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
|
||||||
|
libapi "dev.sum7.de/sum7/warehost/lib/api"
|
||||||
|
libsystem "dev.sum7.de/sum7/warehost/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PermissionList to add permissions
|
||||||
|
func (api *API) PermissionList(w http.ResponseWriter, r *http.Request, _ httprouter.Params, sess session.Session, login *libsystem.Login, websiteid int64) (returndata interface{}, returnerr *libapi.ErrorResult) {
|
||||||
|
returndata = false
|
||||||
|
logger := api.log.GetLog(r, "permissionlist")
|
||||||
|
var involved []*Manager
|
||||||
|
api.dbconnection.Where("website = ?", websiteid).Preload("Login").Find(&involved)
|
||||||
|
logger.Info("done")
|
||||||
|
returndata = involved
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// PermissionAdd to add permissions
|
||||||
|
func (api *API) PermissionAdd(w http.ResponseWriter, r *http.Request, ps httprouter.Params, sess session.Session, login *libsystem.Login, websiteid int64) (returndata interface{}, returnerr *libapi.ErrorResult) {
|
||||||
|
returndata = false
|
||||||
|
logger := api.log.GetLog(r, "permissionadd")
|
||||||
|
loginid, err := strconv.ParseInt(ps.ByName("loginid"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
returnerr = &libapi.ErrorResult{Fields: []string{"loginid"}, Message: "Not a valid loginid"}
|
||||||
|
logger.Warn("invalid loginid, no integer")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
manager := &Manager{
|
||||||
|
WebsiteID: websiteid,
|
||||||
|
LoginID: loginid,
|
||||||
|
}
|
||||||
|
if err := api.dbconnection.Create(manager).Error; err != nil {
|
||||||
|
logger.Error("database: during create website permission")
|
||||||
|
returnerr = &libapi.ErrorResult{Message: "Internal Database Error"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
returndata = true
|
||||||
|
logger.Info("done")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// PermissionDelete to delete permissions
|
||||||
|
func (api *API) PermissionDelete(w http.ResponseWriter, r *http.Request, ps httprouter.Params, sess session.Session, login *libsystem.Login, websiteid int64) (returndata interface{}, returnerr *libapi.ErrorResult) {
|
||||||
|
returndata = false
|
||||||
|
logger := api.log.GetLog(r, "permissiondelete")
|
||||||
|
loginid, err := strconv.ParseInt(ps.ByName("loginid"), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
returnerr = &libapi.ErrorResult{Fields: []string{"loginid"}, Message: "Not a valid loginid"}
|
||||||
|
logger.Warn("invalid loginid, no integer")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
manager := &Manager{
|
||||||
|
WebsiteID: websiteid,
|
||||||
|
LoginID: loginid,
|
||||||
|
}
|
||||||
|
if err := api.dbconnection.Unscoped().Delete(manager).Error; err != nil {
|
||||||
|
logger.Error("database: during delete website permission")
|
||||||
|
returnerr = &libapi.ErrorResult{Message: "Internal Database Error"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
returndata = true
|
||||||
|
logger.Info("done")
|
||||||
|
return
|
||||||
|
}
|
|
@ -3,7 +3,8 @@ package web
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
//system "dev.sum7.de/sum7/warehost/system"
|
|
||||||
|
system "dev.sum7.de/sum7/warehost/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Website struct
|
// Website struct
|
||||||
|
@ -27,9 +28,10 @@ func (Domain) TableName() string { return "web_domain" }
|
||||||
|
|
||||||
// Manager struct
|
// Manager struct
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
LoginID int64 `sql:"type:bigint REFERENCES login(id) ON UPDATE CASCADE ON DELETE CASCADE;column:login;primary_key" json:"login"`
|
LoginID int64 `sql:"type:bigint REFERENCES login(id) ON UPDATE CASCADE ON DELETE CASCADE;column:login;primary_key" json:"-"`
|
||||||
WebsiteID int64 `sql:"type:bigint REFERENCES web_website(id) ON UPDATE CASCADE ON DELETE CASCADE;column:website;primary_key" json:"-"`
|
Login system.Login `gorm:"foreignkey:Login" json:"login"`
|
||||||
Website Website `gorm:"foreignkey:Website" json:"website"`
|
WebsiteID int64 `sql:"type:bigint REFERENCES web_website(id) ON UPDATE CASCADE ON DELETE CASCADE;column:website;primary_key" json:"-"`
|
||||||
|
Website Website `gorm:"foreignkey:Website" json:"website"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName of struct
|
// TableName of struct
|
||||||
|
|
|
@ -43,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/:id", LoginHandler(api.LoginEdit, sessions))
|
router.GET(prefix+"/user", LoginHandler(api.LoginList, sessions))
|
||||||
router.DELETE(prefix+"/invite/:id", LoginHandler(api.LoginDelete, sessions))
|
router.POST(prefix+"/user", LoginHandler(api.LoginAdd, sessions))
|
||||||
|
router.PUT(prefix+"/user/:id", LoginHandler(api.LoginEdit, sessions))
|
||||||
|
router.DELETE(prefix+"/user/:id", LoginHandler(api.LoginDelete, sessions))
|
||||||
router.GET(prefix+"/invitor", LoginHandler(api.Invitor, sessions))
|
router.GET(prefix+"/invitor", LoginHandler(api.Invitor, sessions))
|
||||||
router.PUT(prefix+"/invitor", LoginHandler(api.InvitorAdminToggle, sessions))
|
router.PUT(prefix+"/invitor", LoginHandler(api.InvitorAdminToggle, sessions))
|
||||||
}
|
}
|
||||||
|
@ -58,7 +60,7 @@ func (api *API) Status(w http.ResponseWriter, r *http.Request, _ httprouter.Para
|
||||||
if result > 0 {
|
if result > 0 {
|
||||||
returndata = true
|
returndata = true
|
||||||
}
|
}
|
||||||
logger.Info("status")
|
logger.Info("done")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +73,7 @@ func (api *API) Logout(w http.ResponseWriter, r *http.Request, _ httprouter.Para
|
||||||
}
|
}
|
||||||
sess.Delete("login")
|
sess.Delete("login")
|
||||||
sess.Delete("profil")
|
sess.Delete("profil")
|
||||||
logger.Info("logout")
|
logger.Info("done")
|
||||||
returndata = true
|
returndata = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -104,7 +106,7 @@ func (api *API) Login(w http.ResponseWriter, r *http.Request, _ httprouter.Param
|
||||||
returndata = true
|
returndata = true
|
||||||
api.dbconnection.Model(&login).Update("LastLoginAt", time.Now())
|
api.dbconnection.Model(&login).Update("LastLoginAt", time.Now())
|
||||||
sess.Set("login", login)
|
sess.Set("login", login)
|
||||||
logger.Info("logged in")
|
logger.Info("done")
|
||||||
} else {
|
} else {
|
||||||
logger.Warn("wrong password")
|
logger.Warn("wrong password")
|
||||||
returnerr = &libapi.ErrorResult{Fields: []string{"password"}, Message: "Wrong Password"}
|
returnerr = &libapi.ErrorResult{Fields: []string{"password"}, Message: "Wrong Password"}
|
||||||
|
@ -149,7 +151,7 @@ func (api *API) Password(w http.ResponseWriter, r *http.Request, _ httprouter.Pa
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sess.Set("login", *login)
|
sess.Set("login", *login)
|
||||||
logger.Info("works")
|
logger.Info("done")
|
||||||
returndata = true
|
returndata = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -164,7 +166,7 @@ func (api *API) Delete(w http.ResponseWriter, r *http.Request, _ httprouter.Para
|
||||||
returnerr = &libapi.ErrorResult{Message: "Error delete login"}
|
returnerr = &libapi.ErrorResult{Message: "Error delete login"}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Warn("login delete")
|
logger.Warn("done")
|
||||||
returndata = true
|
returndata = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -173,12 +175,12 @@ func (api *API) Delete(w http.ResponseWriter, r *http.Request, _ httprouter.Para
|
||||||
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
|
returndata = false
|
||||||
logger := api.log.GetLog(r, "invitelist")
|
logger := api.log.GetLog(r, "invitelist")
|
||||||
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!"}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
logger.Info("done")
|
||||||
returndata = login.Invites
|
returndata = login.Invites
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -208,7 +210,58 @@ func (api *API) InviteAdd(w http.ResponseWriter, r *http.Request, _ httprouter.P
|
||||||
returnerr = &libapi.ErrorResult{Message: "Username exists already"}
|
returnerr = &libapi.ErrorResult{Message: "Username exists already"}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Info("invite")
|
logger.Info("done")
|
||||||
|
returndata = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoginList list all users in system
|
||||||
|
func (api *API) LoginList(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, "loginlist")
|
||||||
|
var logins []Login
|
||||||
|
selectfield := "ID, mail"
|
||||||
|
if login.Superadmin {
|
||||||
|
selectfield = "ID, mail, superadmin"
|
||||||
|
}
|
||||||
|
if err := api.dbconnection.Select(selectfield).Find(&logins).Error; err != nil {
|
||||||
|
logger.Warn("sql edit login")
|
||||||
|
returnerr = &libapi.ErrorResult{Message: "Error during edit login"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.Info("done")
|
||||||
|
returndata = logins
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoginAdd add a new Login
|
||||||
|
func (api *API) LoginAdd(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, "loginadd")
|
||||||
|
if !login.Superadmin {
|
||||||
|
logger.Error("no superadmin")
|
||||||
|
returnerr = &libapi.ErrorResult{Message: "Error no permission to edit this invite"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var newLogin RequestLogin
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&newLogin)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("fetch request")
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
returnerr = &libapi.ErrorResult{Message: "Internal Request Error"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
loginObj := Login{
|
||||||
|
Username: strings.ToLower(newLogin.Username),
|
||||||
|
Password: libpassword.NewHash(newLogin.Password),
|
||||||
|
Active: true,
|
||||||
|
}
|
||||||
|
if err := api.dbconnection.Create(loginObj).Error; err != nil {
|
||||||
|
logger.Warn("error create login")
|
||||||
|
returnerr = &libapi.ErrorResult{Message: "Username exists already"}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.Info("done")
|
||||||
returndata = true
|
returndata = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -238,7 +291,7 @@ func (api *API) LoginEdit(w http.ResponseWriter, r *http.Request, ps httprouter.
|
||||||
invite := invitedLogin.GetInvitedby(api.dbconnection)
|
invite := invitedLogin.GetInvitedby(api.dbconnection)
|
||||||
if !login.Superadmin && !invite.Admin && invitedLogin.CreateAt.Before(invitedLogin.LastLoginAt) {
|
if !login.Superadmin && !invite.Admin && invitedLogin.CreateAt.Before(invitedLogin.LastLoginAt) {
|
||||||
logger.Warn("no permission")
|
logger.Warn("no permission")
|
||||||
returnerr = &libapi.ErrorResult{Message: "Error no permission to edit this invite"}
|
returnerr = &libapi.ErrorResult{Message: "Error no permission to edit this login"}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(changeLogin.Password) > 0 {
|
if len(changeLogin.Password) > 0 {
|
||||||
|
@ -246,13 +299,14 @@ func (api *API) LoginEdit(w http.ResponseWriter, r *http.Request, ps httprouter.
|
||||||
}
|
}
|
||||||
if login.Superadmin {
|
if login.Superadmin {
|
||||||
invitedLogin.Username = changeLogin.Username
|
invitedLogin.Username = changeLogin.Username
|
||||||
|
invitedLogin.Superadmin = changeLogin.Superadmin
|
||||||
}
|
}
|
||||||
if err := api.dbconnection.Save(invitedLogin).Error; err != nil {
|
if err := api.dbconnection.Save(invitedLogin).Error; err != nil {
|
||||||
logger.Warn("sql edit login")
|
logger.Warn("sql edit login")
|
||||||
returnerr = &libapi.ErrorResult{Message: "Error during edit login"}
|
returnerr = &libapi.ErrorResult{Message: "Error during edit login"}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Info("login edit")
|
logger.Info("done")
|
||||||
returndata = true
|
returndata = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -273,7 +327,7 @@ func (api *API) LoginDelete(w http.ResponseWriter, r *http.Request, ps httproute
|
||||||
invite := invitedLogin.GetInvitedby(api.dbconnection)
|
invite := invitedLogin.GetInvitedby(api.dbconnection)
|
||||||
if !login.Superadmin && !invite.Admin && invitedLogin.CreateAt.Before(invitedLogin.LastLoginAt) {
|
if !login.Superadmin && !invite.Admin && invitedLogin.CreateAt.Before(invitedLogin.LastLoginAt) {
|
||||||
logger.Warn("no permission")
|
logger.Warn("no permission")
|
||||||
returnerr = &libapi.ErrorResult{Message: "Error no permission to delete this invite"}
|
returnerr = &libapi.ErrorResult{Message: "Error no permission to delete this login"}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := api.dbconnection.Unscoped().Delete(invitedLogin).Error; err != nil {
|
if err := api.dbconnection.Unscoped().Delete(invitedLogin).Error; err != nil {
|
||||||
|
@ -281,7 +335,7 @@ func (api *API) LoginDelete(w http.ResponseWriter, r *http.Request, ps httproute
|
||||||
returnerr = &libapi.ErrorResult{Message: "Error during delete login"}
|
returnerr = &libapi.ErrorResult{Message: "Error during delete login"}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Info("login deleted")
|
logger.Info("done")
|
||||||
returndata = true
|
returndata = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -291,7 +345,7 @@ func (api *API) Invitor(w http.ResponseWriter, r *http.Request, ps httprouter.Pa
|
||||||
returndata = false
|
returndata = false
|
||||||
logger := api.log.GetLog(r, "invitor")
|
logger := api.log.GetLog(r, "invitor")
|
||||||
invite := login.GetInvitedby(api.dbconnection)
|
invite := login.GetInvitedby(api.dbconnection)
|
||||||
logger.Info("show invitor")
|
logger.Info("done")
|
||||||
returndata = invite
|
returndata = invite
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -303,7 +357,7 @@ func (api *API) InvitorAdminToggle(w http.ResponseWriter, r *http.Request, ps ht
|
||||||
invite := login.GetInvitedby(api.dbconnection)
|
invite := login.GetInvitedby(api.dbconnection)
|
||||||
invite.Admin = !invite.Admin
|
invite.Admin = !invite.Admin
|
||||||
api.dbconnection.Model(invite).Save(&invite)
|
api.dbconnection.Model(invite).Save(&invite)
|
||||||
logger.Info("toggle saved")
|
logger.Info("done")
|
||||||
returndata = true
|
returndata = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,9 @@ const MINPASSWORDLENTH = 3
|
||||||
|
|
||||||
// RequestLogin for api request to log in
|
// RequestLogin for api request to log in
|
||||||
type RequestLogin struct {
|
type RequestLogin struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
|
Superadmin bool `json:"superadmin,oemitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChangePasswordRequest for api request of a new password
|
// ChangePasswordRequest for api request of a new password
|
||||||
|
|
2
webroot
2
webroot
|
@ -1 +1 @@
|
||||||
Subproject commit c9fd753cfa6904337406706a94dbc5f4af43d4bb
|
Subproject commit ed433dc66f10a99f1a7ac3df538bc072e8e1881c
|
Reference in New Issue