add ability to remove user and add task depndencies closes #69
This commit is contained in:
@@ -68,35 +68,25 @@ type BaseModel struct {
|
||||
Status int
|
||||
Id string
|
||||
|
||||
ModelType int
|
||||
ImageMode int
|
||||
Width int
|
||||
Height int
|
||||
Format string
|
||||
ModelType int `db:"model_type"`
|
||||
ImageModeRaw string `db:"color_mode"`
|
||||
ImageMode int `db:"0"`
|
||||
Width int
|
||||
Height int
|
||||
Format string
|
||||
CanTrain int `db:"can_train"`
|
||||
}
|
||||
|
||||
var ModelNotFoundError = errors.New("Model not found error")
|
||||
|
||||
func GetBaseModel(db *sql.DB, id string) (base *BaseModel, err error) {
|
||||
rows, err := db.Query("select name, status, id, width, height, color_mode, format, model_type from models where id=$1;", id)
|
||||
var model BaseModel
|
||||
err = GetDBOnce(db, &model, "models where id=$1", id)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if !rows.Next() {
|
||||
return nil, ModelNotFoundError
|
||||
}
|
||||
|
||||
base = &BaseModel{}
|
||||
var colorMode string
|
||||
err = rows.Scan(&base.Name, &base.Status, &base.Id, &base.Width, &base.Height, &colorMode, &base.Format, &base.ModelType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
base.ImageMode = StringToImageMode(colorMode)
|
||||
return
|
||||
model.ImageMode = StringToImageMode(model.ImageModeRaw)
|
||||
return &model, nil
|
||||
}
|
||||
|
||||
func (m BaseModel) CanEval() bool {
|
||||
|
||||
@@ -7,7 +7,8 @@ import (
|
||||
type UserType int
|
||||
|
||||
const (
|
||||
User_Not_Auth UserType = iota
|
||||
User_Deleted UserType = iota - 1
|
||||
User_Not_Auth
|
||||
User_Normal
|
||||
User_Admin
|
||||
)
|
||||
|
||||
@@ -439,6 +439,8 @@ func handleDataUpload(handle *Handle) {
|
||||
return c.SendJSONStatus(http.StatusNotFound, "Model not found")
|
||||
} else if err != nil {
|
||||
return c.Error500(err)
|
||||
} else if model.CanTrain == 0 {
|
||||
return c.JsonBadRequest("Model can not be trained!")
|
||||
}
|
||||
|
||||
// TODO mk this path configurable
|
||||
@@ -468,6 +470,10 @@ func handleDataUpload(handle *Handle) {
|
||||
model, err := GetBaseModel(c.Db, obj.Id)
|
||||
if err == ModelNotFoundError {
|
||||
return c.JsonBadRequest("Model not found")
|
||||
} else if err != nil {
|
||||
return c.E500M("Failed to get model information", err)
|
||||
} else if model.CanTrain == 0 {
|
||||
return c.JsonBadRequest("Model can not be trained!")
|
||||
}
|
||||
|
||||
if model.ModelType != 2 && model.Status != CONFIRM_PRE_TRAINING || model.ModelType == 2 && model.Status != CONFIRM_PRE_TRAINING && model.Status != READY {
|
||||
@@ -516,6 +522,8 @@ func handleDataUpload(handle *Handle) {
|
||||
return c.JsonBadRequest("Could not find the model")
|
||||
} else if err != nil {
|
||||
return c.E500M("Error getting model information", err)
|
||||
} else if model.CanTrain == 0 {
|
||||
return c.JsonBadRequest("Model can not be trained!")
|
||||
}
|
||||
|
||||
// TODO make this work for zip files as well
|
||||
@@ -622,6 +630,8 @@ func handleDataUpload(handle *Handle) {
|
||||
return c.SendJSONStatus(http.StatusNotFound, "Model not found")
|
||||
} else if err != nil {
|
||||
return c.Error500(err)
|
||||
} else if model.CanTrain == 0 {
|
||||
return c.JsonBadRequest("Model can not be trained!")
|
||||
}
|
||||
|
||||
// TODO work in allowing the model to add new in the pre ready moment
|
||||
|
||||
@@ -9,20 +9,27 @@ import (
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||
)
|
||||
|
||||
func deleteModelJSON(c *Context, id string) *Error {
|
||||
c.Logger.Warnf("Removing model with id: %s", id)
|
||||
_, err := c.Db.Exec("delete from models where id=$1;", id)
|
||||
func DeleteModel(c BasePack, id string) (err error) {
|
||||
c.GetLogger().Warnf("Removing model with id: %s", id)
|
||||
_, err = c.GetDb().Exec("delete from models where id=$1;", id)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to delete models", err)
|
||||
return
|
||||
}
|
||||
|
||||
model_path := path.Join("./savedData", id)
|
||||
c.Logger.Warnf("Removing folder of model with id: %s at %s", id, model_path)
|
||||
c.GetLogger().Warnf("Removing folder of model with id: %s at %s", id, model_path)
|
||||
err = os.RemoveAll(model_path)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to remove data", err)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func deleteModelJSON(c *Context, id string) *Error {
|
||||
err := DeleteModel(c, id)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to delete models", err)
|
||||
}
|
||||
return c.SendJSON(id)
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ func runModelExp(base BasePack, model *BaseModel, def_id string, inputImage *tf.
|
||||
func ClassifyTask(base BasePack, task Task) (err error) {
|
||||
task.UpdateStatusLog(base, TASK_RUNNING, "Runner running task")
|
||||
|
||||
model, err := GetBaseModel(base.GetDb(), task.ModelId)
|
||||
model, err := GetBaseModel(base.GetDb(), *task.ModelId)
|
||||
if err != nil {
|
||||
task.UpdateStatusLog(base, TASK_FAILED_RUNNING, "Failed to obtain the model")
|
||||
return err
|
||||
|
||||
@@ -1625,7 +1625,7 @@ func trainExpandable(c *Context, model *BaseModel) {
|
||||
func RunTaskTrain(b BasePack, task Task) (err error) {
|
||||
l := b.GetLogger()
|
||||
|
||||
model, err := GetBaseModel(b.GetDb(), task.ModelId)
|
||||
model, err := GetBaseModel(b.GetDb(), *task.ModelId)
|
||||
if err != nil {
|
||||
task.UpdateStatusLog(b, TASK_FAILED_RUNNING, "Failed to get model information")
|
||||
l.Error("Failed to get model information", "err", err)
|
||||
@@ -1683,7 +1683,7 @@ func RunTaskTrain(b BasePack, task Task) (err error) {
|
||||
}
|
||||
|
||||
func RunTaskRetrain(b BasePack, task Task) (err error) {
|
||||
model, err := GetBaseModel(b.GetDb(), task.ModelId)
|
||||
model, err := GetBaseModel(b.GetDb(), *task.ModelId)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if model.Status != READY_RETRAIN {
|
||||
@@ -1759,6 +1759,8 @@ func handleTrain(handle *Handle) {
|
||||
return c.JsonBadRequest("Model not found")
|
||||
} else if err != nil {
|
||||
return c.E500M("Failed to get model information", err)
|
||||
} else if model.CanTrain == 0 {
|
||||
return c.JsonBadRequest("Model can not be trained!")
|
||||
}
|
||||
|
||||
if model.Status != CONFIRM_PRE_TRAINING {
|
||||
@@ -1813,6 +1815,8 @@ func handleTrain(handle *Handle) {
|
||||
return c.E500M("Faield to get model", err)
|
||||
} else if model.Status != READY && model.Status != READY_RETRAIN_FAILED && model.Status != READY_ALTERATION_FAILED {
|
||||
return c.JsonBadRequest("Model in invalid status for re-training")
|
||||
} else if model.CanTrain == 0 {
|
||||
return c.JsonBadRequest("Model can not be trained!")
|
||||
}
|
||||
|
||||
c.Logger.Info("Expanding definitions for models", "id", model.Id)
|
||||
|
||||
@@ -55,6 +55,8 @@ func handleUpload(handler *Handle) {
|
||||
model, err := GetBaseModel(c.Db, requestData.ModelId)
|
||||
if err != nil {
|
||||
return c.Error500(err)
|
||||
} else if model.CanTrain == 0 {
|
||||
return c.JsonBadRequest("Model can not be trained!")
|
||||
}
|
||||
|
||||
switch model.Status {
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/train"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/users"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||
)
|
||||
|
||||
@@ -71,6 +72,14 @@ func runner(config Config, db *sql.DB, task_channel chan Task, index int, back_c
|
||||
logger.Error("Failed to tain the model", "error", err)
|
||||
}
|
||||
|
||||
back_channel <- index
|
||||
continue
|
||||
} else if task.TaskType == int(TASK_TYPE_DELETE_USER) {
|
||||
logger.Warn("User deleting Task")
|
||||
if err = DeleteUser(base, task); err != nil {
|
||||
logger.Error("Failed to tain the model", "error", err)
|
||||
}
|
||||
|
||||
back_channel <- index
|
||||
continue
|
||||
}
|
||||
@@ -168,16 +177,23 @@ func RunnerOrchestrator(db *sql.DB, config Config) {
|
||||
}
|
||||
|
||||
if task_to_dispatch == nil {
|
||||
var task Task
|
||||
err := GetDBOnce(db, &task, "tasks where status=$1 limit 1", TASK_TODO)
|
||||
var task TaskT
|
||||
err := GetDBOnce(db, &task, "tasks as t "+
|
||||
// Get depenencies
|
||||
"left join tasks_dependencies as td on t.id=td.main_id "+
|
||||
// Get the task that the depencey resolves to
|
||||
"left join tasks as t2 on t2.id=td.dependent_id "+
|
||||
"where t.status=1 "+
|
||||
"group by t.id having count(td.id) filter (where t2.status in (0,1,2,3)) = 0;")
|
||||
if err != NotFoundError && err != nil {
|
||||
log.Error("Failed to get tasks from db")
|
||||
log.Error("Failed to get tasks from db", "err", err)
|
||||
continue
|
||||
}
|
||||
if err == NotFoundError {
|
||||
task_to_dispatch = nil
|
||||
} else {
|
||||
task_to_dispatch = &task
|
||||
temp := Task(task)
|
||||
task_to_dispatch = &temp
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
type Task struct {
|
||||
Id string `db:"id" json:"id"`
|
||||
UserId string `db:"user_id" json:"user_id"`
|
||||
ModelId string `db:"model_id" json:"model_id"`
|
||||
ModelId *string `db:"model_id" json:"model_id"`
|
||||
Status int `db:"status" json:"status"`
|
||||
StatusMessage string `db:"status_message" json:"status_message"`
|
||||
UserConfirmed int `db:"user_confirmed" json:"user_confirmed"`
|
||||
@@ -21,6 +21,27 @@ type Task struct {
|
||||
CreatedOn time.Time `db:"created_on" json:"created"`
|
||||
}
|
||||
|
||||
// Find better way todo this
|
||||
type TaskT struct {
|
||||
Id string `db:"t.id" json:"id"`
|
||||
UserId string `db:"t.user_id" json:"user_id"`
|
||||
ModelId *string `db:"t.model_id" json:"model_id"`
|
||||
Status int `db:"t.status" json:"status"`
|
||||
StatusMessage string `db:"t.status_message" json:"status_message"`
|
||||
UserConfirmed int `db:"t.user_confirmed" json:"user_confirmed"`
|
||||
Compacted int `db:"t.compacted" json:"compacted"`
|
||||
TaskType int `db:"t.task_type" json:"type"`
|
||||
ExtraTaskInfo string `db:"t.extra_task_info" json:"extra_task_info"`
|
||||
Result string `db:"t.result" json:"result"`
|
||||
CreatedOn time.Time `db:"t.created_on" json:"created"`
|
||||
}
|
||||
|
||||
type TaskDependents struct {
|
||||
Id string `db:"id" json:"id"`
|
||||
MainId string `db:"main_id" json:"main_id"`
|
||||
DependentId string `db:"dependent_id" json:"dependent_id"`
|
||||
}
|
||||
|
||||
type TaskStatus int
|
||||
|
||||
const (
|
||||
@@ -39,6 +60,7 @@ const (
|
||||
TASK_TYPE_CLASSIFICATION TaskType = 1 + iota
|
||||
TASK_TYPE_TRAINING
|
||||
TASK_TYPE_RETRAINING
|
||||
TASK_TYPE_DELETE_USER
|
||||
)
|
||||
|
||||
type TaskAgreement int
|
||||
@@ -82,3 +104,15 @@ func (t Task) SetResult(base BasePack, result any) (err error) {
|
||||
_, err = base.GetDb().Exec("update tasks set result=$1 where id=$2", text, t.Id)
|
||||
return
|
||||
}
|
||||
|
||||
func (t Task) Depend(base BasePack, depend_id string) (err error) {
|
||||
var dependency = struct {
|
||||
Main string `db:"main_id"`
|
||||
Dependent string `db:"dependent_id"`
|
||||
}{
|
||||
Main: t.Id,
|
||||
Dependent: depend_id,
|
||||
}
|
||||
_, err = InsertReturnId(base.GetDb(), &dependency, "tasks_dependencies", "id")
|
||||
return
|
||||
}
|
||||
|
||||
492
logic/users/users.go
Normal file
492
logic/users/users.go
Normal file
@@ -0,0 +1,492 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
|
||||
dbtypes "git.andr3h3nriqu3s.com/andr3/fyp/logic/db_types"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/utils"
|
||||
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
|
||||
)
|
||||
|
||||
func generateSalt() string {
|
||||
salt := make([]byte, 4)
|
||||
_, err := io.ReadFull(rand.Reader, salt)
|
||||
if err != nil {
|
||||
panic("TODO handle this better")
|
||||
}
|
||||
return hex.EncodeToString(salt)
|
||||
}
|
||||
|
||||
func hashPassword(password string, salt string) (string, error) {
|
||||
bytes_salt, err := hex.DecodeString(salt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
bytes, err := bcrypt.GenerateFromPassword(append([]byte(password), bytes_salt...), 14)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func genToken() string {
|
||||
token := make([]byte, 60)
|
||||
_, err := io.ReadFull(rand.Reader, token)
|
||||
if err != nil {
|
||||
panic("TODO handle this better")
|
||||
}
|
||||
return hex.EncodeToString(token)
|
||||
}
|
||||
|
||||
func deleteToken(db *sql.DB, userId string, time time.Time) (err error) {
|
||||
_, err = db.Exec("delete from tokens where emit_day=$1 and user_id=$2", time, userId)
|
||||
return
|
||||
}
|
||||
|
||||
func generateToken(db *sql.DB, email string, password string, name string) (string, bool) {
|
||||
row, err := db.Query("select id, salt, password from users where email = $1;", email)
|
||||
if err != nil || !row.Next() {
|
||||
return "", false
|
||||
}
|
||||
|
||||
var db_id string
|
||||
var db_salt string
|
||||
var db_password string
|
||||
err = row.Scan(&db_id, &db_salt, &db_password)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
bytes_salt, err := hex.DecodeString(db_salt)
|
||||
if err != nil {
|
||||
panic("TODO handle better! Somethign is wrong with salt being stored in the database")
|
||||
}
|
||||
|
||||
if err = bcrypt.CompareHashAndPassword([]byte(db_password), append([]byte(password), bytes_salt...)); err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
token := genToken()
|
||||
|
||||
_, err = db.Exec("insert into tokens (user_id, token, name) values ($1, $2, $3);", db_id, token, name)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return token, true
|
||||
}
|
||||
|
||||
func DeleteUser(base BasePack, task Task) (err error) {
|
||||
ids, err := GetDbMultitple[JustId](base.GetDb(), "models where user_id=$1;", task.ExtraTaskInfo)
|
||||
if err != nil {
|
||||
task.UpdateStatusLog(base, TASK_FAILED_RUNNING, "Could not get models list")
|
||||
return
|
||||
}
|
||||
|
||||
for i := range ids {
|
||||
err = DeleteModel(base, ids[i].Id)
|
||||
if err != nil {
|
||||
base.GetLogger().Error("Could not delete model", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = base.GetDb().Exec("delete from users where id=$1", task.ExtraTaskInfo)
|
||||
if err != nil {
|
||||
task.UpdateStatusLog(base, TASK_FAILED_RUNNING, "Could not delete user")
|
||||
return
|
||||
}
|
||||
|
||||
task.UpdateStatusLog(base, TASK_DONE, "User deleted with success")
|
||||
return
|
||||
}
|
||||
|
||||
func UsersEndpints(db *sql.DB, handle *Handle) {
|
||||
|
||||
type UserLogin struct {
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
PostAuthJson(handle, "/login", dbtypes.User_Not_Auth, func(c *Context, dat *UserLogin) *Error {
|
||||
// TODO Give this to the generateToken function
|
||||
token, login := generateToken(db, dat.Email, dat.Password, "Logged in user")
|
||||
if !login {
|
||||
return c.SendJSONStatus(http.StatusUnauthorized, "Email or password are incorrect")
|
||||
}
|
||||
|
||||
user, err := dbtypes.UserFromToken(c.Db, token)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to get user from token", err)
|
||||
}
|
||||
|
||||
if user.UserType == int(User_Deleted) {
|
||||
return c.JsonBadRequest("Your user is in the process of being deleted!")
|
||||
}
|
||||
|
||||
type UserReturn struct {
|
||||
Token string `json:"token"`
|
||||
Id string `json:"id"`
|
||||
UserType int `json:"user_type"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
userReturn := UserReturn{
|
||||
Token: token,
|
||||
Id: user.Id,
|
||||
UserType: user.UserType,
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
}
|
||||
|
||||
return c.SendJSON(userReturn)
|
||||
})
|
||||
|
||||
type UserRegister struct {
|
||||
Username string `json:"username" validate:"required"`
|
||||
Email string `json:"email" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
}
|
||||
PostAuthJson(handle, "/register", dbtypes.User_Not_Auth, func(c *Context, dat *UserRegister) *Error {
|
||||
|
||||
var prevUser struct {
|
||||
Username string
|
||||
Email string
|
||||
}
|
||||
err := GetDBOnce(c, &prevUser, "users where username=$1 or email=$2;", dat.Username, dat.Email)
|
||||
if err == NotFoundError {
|
||||
// Do nothing the user does not exist and it's ok to create a new one
|
||||
} else if err != nil {
|
||||
return c.E500M("Falied to get user data", err)
|
||||
} else {
|
||||
if prevUser.Email == dat.Email {
|
||||
return c.SendJSONStatus(http.StatusBadRequest, "Email already in use!")
|
||||
}
|
||||
if prevUser.Username == dat.Username {
|
||||
return c.SendJSONStatus(http.StatusBadRequest, "Username already in use!")
|
||||
}
|
||||
}
|
||||
|
||||
if len([]byte(dat.Password)) > 68 {
|
||||
return c.JsonBadRequest("Password is to long!")
|
||||
}
|
||||
|
||||
salt := generateSalt()
|
||||
hash_password, err := hashPassword(dat.Password, salt)
|
||||
if err != nil {
|
||||
return c.E500M("Falied to store password", err)
|
||||
}
|
||||
|
||||
_, err = db.Exec("insert into users (username, email, salt, password) values ($1, $2, $3, $4);", dat.Username, dat.Email, salt, hash_password)
|
||||
if err != nil {
|
||||
return c.E500M("Falied to create user", err)
|
||||
}
|
||||
|
||||
// TODO Give this to the generateToken function
|
||||
token, login := generateToken(db, dat.Email, dat.Password, "User Login")
|
||||
if !login {
|
||||
return c.SendJSONStatus(500, "Could not login after creatting account please try again later")
|
||||
}
|
||||
|
||||
user, err := dbtypes.UserFromToken(c.Db, token)
|
||||
if err != nil {
|
||||
return c.E500M("Falied to create user", err)
|
||||
}
|
||||
|
||||
type UserReturn struct {
|
||||
Token string `json:"token"`
|
||||
Id string `json:"id"`
|
||||
UserType int `json:"user_type"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
userReturn := UserReturn{
|
||||
Token: token,
|
||||
Id: user.Id,
|
||||
UserType: user.UserType,
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
}
|
||||
|
||||
return c.SendJSON(userReturn)
|
||||
})
|
||||
|
||||
// TODO allow admin users to update this data
|
||||
handle.GetAuth("/user/info", dbtypes.User_Normal, func(c *Context) *Error {
|
||||
user, err := dbtypes.UserFromToken(c.Db, *c.Token)
|
||||
if err != nil {
|
||||
return c.E500M("Falied to get user data", err)
|
||||
}
|
||||
|
||||
type UserReturn struct {
|
||||
Id string `json:"id"`
|
||||
UserType int `json:"user_type"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
userReturn := UserReturn{
|
||||
Id: user.Id,
|
||||
UserType: user.UserType,
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
}
|
||||
|
||||
return c.SendJSON(userReturn)
|
||||
})
|
||||
|
||||
// Handles updating users
|
||||
type UpdateUserData struct {
|
||||
Id string `json:"id"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
PostAuthJson(handle, "/user/info", dbtypes.User_Normal, func(c *Context, dat *UpdateUserData) *Error {
|
||||
if dat.Id != c.User.Id && c.User.UserType != int(dbtypes.User_Admin) {
|
||||
return c.SendJSONStatus(403, "You need to be an admin to update another users account")
|
||||
}
|
||||
|
||||
if dat.Id != c.User.Id {
|
||||
var data struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
err := GetDBOnce(c, &data, "users where id=$1", dat.Id)
|
||||
if err == NotFoundError {
|
||||
return c.JsonBadRequest("User does not exist")
|
||||
} else if err != nil {
|
||||
return c.E500M("Falied to get data for user", err)
|
||||
}
|
||||
}
|
||||
|
||||
var data JustId
|
||||
err := GetDBOnce(c, &data, "users where email=$1", dat.Email)
|
||||
if err != nil && err != NotFoundError {
|
||||
return c.E500M("Falied to get data for user", err)
|
||||
}
|
||||
|
||||
if err != NotFoundError {
|
||||
if data.Id == dat.Id {
|
||||
return c.JsonBadRequest("Email is the name as the previous one!")
|
||||
} else {
|
||||
return c.JsonBadRequest("Email already in use")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = c.Db.Exec("update users set email=$2 where id=$1", dat.Id, dat.Email)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to update data", err)
|
||||
}
|
||||
|
||||
var user struct {
|
||||
Id string
|
||||
Username string
|
||||
Email string
|
||||
User_Type int
|
||||
}
|
||||
|
||||
err = GetDBOnce(c, &user, "users where id=$1", dat.Id)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to get user data", err)
|
||||
}
|
||||
|
||||
toReturnUser := dbtypes.User{
|
||||
Id: user.Id,
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
UserType: user.User_Type,
|
||||
}
|
||||
|
||||
return c.SendJSON(toReturnUser)
|
||||
})
|
||||
|
||||
type PasswordUpdate struct {
|
||||
Old_Password string `json:"old_password" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
Password2 string `json:"password2" validate:"required"`
|
||||
}
|
||||
PostAuthJson(handle, "/user/info/password", dbtypes.User_Normal, func(c *Context, dat *PasswordUpdate) *Error {
|
||||
if dat.Password != dat.Password2 {
|
||||
return c.JsonBadRequest("New passwords did not match")
|
||||
}
|
||||
|
||||
// TODO remote token
|
||||
_, login := generateToken(db, c.User.Email, dat.Old_Password, "Update password Token")
|
||||
if !login {
|
||||
return c.JsonBadRequest("Password is incorrect")
|
||||
}
|
||||
|
||||
salt := generateSalt()
|
||||
hash_password, err := hashPassword(dat.Password, salt)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to parse the password", err)
|
||||
}
|
||||
|
||||
_, err = db.Exec("update users set salt=$1, password=$2 where id=$3", salt, hash_password, c.User.Id)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to update password", err)
|
||||
}
|
||||
|
||||
return c.SendJSON(c.User.Id)
|
||||
})
|
||||
|
||||
type TokenList struct {
|
||||
Id string `json:"id"`
|
||||
Page int `json:"page"`
|
||||
}
|
||||
PostAuthJson[TokenList](handle, "/user/token/list", 1, func(c *Context, obj *TokenList) *Error {
|
||||
if obj.Id == "" {
|
||||
obj.Id = c.User.Id
|
||||
}
|
||||
|
||||
if obj.Id != c.User.Id && c.User.UserType < int(dbtypes.User_Admin) {
|
||||
return c.JsonBadRequest("Could not find user tokens")
|
||||
}
|
||||
|
||||
type Token struct {
|
||||
CreationDate time.Time `json:"create_date" db:"emit_day"`
|
||||
TimeToLive int `json:"time_to_live" db:"time_to_live"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
tokens, err := GetDbMultitple[Token](c, "tokens where user_id=$1 order by emit_day desc limit 11 offset $2;", obj.Id, 10*obj.Page)
|
||||
if err != nil {
|
||||
return c.E500M("Failed get tokens", err)
|
||||
}
|
||||
|
||||
max_len := min(11, len(tokens))
|
||||
|
||||
c.ShowMessage = false
|
||||
return c.SendJSON(struct {
|
||||
TokenList []*Token `json:"token_list"`
|
||||
ShowNext bool `json:"show_next"`
|
||||
}{
|
||||
tokens[0:max_len],
|
||||
len(tokens) > 10,
|
||||
})
|
||||
})
|
||||
|
||||
type NewToken struct {
|
||||
Name string `json:"name" validate:"required"`
|
||||
ExpiryTime int `json:"expiry"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
}
|
||||
PostAuthJson(handle, "/user/token/add", User_Normal, func(c *Context, obj *NewToken) *Error {
|
||||
// TODO handle this for admin
|
||||
|
||||
token, generated := generateToken(c.Db, c.User.Email, obj.Password, obj.Name)
|
||||
if !generated {
|
||||
return c.JsonBadRequest("Password provided is incorrect")
|
||||
}
|
||||
|
||||
_, err := c.Db.Exec("update tokens set time_to_live=$1 where token=$2 and user_id=$3", obj.ExpiryTime, token, c.User.Id)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to update token info", err)
|
||||
}
|
||||
|
||||
return c.SendJSON(struct {
|
||||
Name string `json:"name"`
|
||||
ExpiryTime int `json:"expiry"`
|
||||
Token string `json:"token"`
|
||||
}{
|
||||
obj.Name, obj.ExpiryTime, token,
|
||||
})
|
||||
})
|
||||
|
||||
type TokenDelete struct {
|
||||
Time time.Time `json:"time" validate:"required"`
|
||||
}
|
||||
DeleteAuthJson(handle, "/user/token", User_Normal, func(c *Context, obj *TokenDelete) *Error {
|
||||
// TODO allow admin user to delete to other persons token
|
||||
|
||||
err := deleteToken(c.Db, c.User.Id, obj.Time)
|
||||
if err != nil {
|
||||
return c.E500M("Could not delete token", err)
|
||||
}
|
||||
|
||||
return c.SendJSON("Ok")
|
||||
})
|
||||
|
||||
type DeleteUser struct {
|
||||
Id string `json:"id" validate:"required"`
|
||||
Password string `json:"password" validate:"required"`
|
||||
}
|
||||
DeleteAuthJson(handle, "/user/delete", User_Normal, func(c *Context, obj *DeleteUser) *Error {
|
||||
// TODO let admin delete users
|
||||
if c.User.Id != obj.Id {
|
||||
return c.E500M("TODO implement this for admins", nil)
|
||||
}
|
||||
|
||||
// TODO let admin delete users
|
||||
// Verify the user password
|
||||
_, generated := generateToken(c.Db, c.User.Email, obj.Password, "User Verification")
|
||||
if !generated {
|
||||
return c.JsonBadRequest("Password provided is incorrect")
|
||||
}
|
||||
|
||||
// Disable the ability for the user to create new tasks
|
||||
_, err := c.Db.Exec(
|
||||
"update models as m set can_train=0 "+
|
||||
"from users as u "+
|
||||
"where u.id=$1 and u.id=m.user_id;",
|
||||
obj.Id,
|
||||
)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to stop the models", err)
|
||||
}
|
||||
|
||||
type CreateNewTask struct {
|
||||
UserId string `db:"user_id"`
|
||||
TaskType int `db:"task_type"`
|
||||
Status int `db:"status"`
|
||||
ExtraTaskInfo string `db:"extra_task_info"`
|
||||
}
|
||||
|
||||
newTask := CreateNewTask{
|
||||
UserId: c.Handle.Config.ServiceUser.UserId,
|
||||
// TODO move this to an enum
|
||||
TaskType: int(TASK_TYPE_DELETE_USER),
|
||||
Status: TASK_PREPARING,
|
||||
ExtraTaskInfo: obj.Id,
|
||||
}
|
||||
t_id, err := InsertReturnId(c, &newTask, "tasks", "id")
|
||||
if err != nil {
|
||||
return c.E500M("Failed to create task", err)
|
||||
}
|
||||
|
||||
task := Task{Id: t_id}
|
||||
|
||||
type taskId struct {
|
||||
Id string `db:"t.id"`
|
||||
}
|
||||
tasks, err := GetDbMultitple[taskId](c, "tasks as t "+
|
||||
"left join models as m on m.id=t.model_id "+
|
||||
"where (t.user_id=$1 or m.user_id=$1) and t.status in (0,1,2,3) "+
|
||||
"group by t.id;",
|
||||
obj.Id)
|
||||
|
||||
for i := range tasks {
|
||||
err = task.Depend(c, tasks[i].Id)
|
||||
if err != nil {
|
||||
c.Logger.Error("Failed to mark task as depency", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = task.UpdateStatus(c, TASK_TODO, "Task ready")
|
||||
if err != nil {
|
||||
return c.E500M("Failed to mark task as ready", err)
|
||||
}
|
||||
|
||||
_, err = c.Db.Exec("update users set user_type=-1 where id=$1", obj.Id)
|
||||
if err != nil {
|
||||
return c.E500M("Failed to delete user", err)
|
||||
}
|
||||
|
||||
return c.SendJSON("User to be deleted")
|
||||
})
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func (c *Config) Cleanup(db *sql.DB) {
|
||||
failLog(err)
|
||||
_, err = db.Exec("update models set status=$1 where status=$2", FAILED_PREPARING, PREPARING)
|
||||
failLog(err)
|
||||
_, err = db.Exec("update tasks set status=$1 where status=$2", TASK_PICKED_UP, TASK_TODO)
|
||||
_, err = db.Exec("update tasks set status=$1 where status=$2", TASK_TODO, TASK_PICKED_UP)
|
||||
failLog(err)
|
||||
|
||||
tasks, err := GetDbMultitple[Task](db, "tasks where status=$1", TASK_RUNNING)
|
||||
|
||||
Reference in New Issue
Block a user