1package projects 2 3import ( 4 "database/sql" 5 "encoding/json" 6 "net/http" 7 8 "github.com/ansible-semaphore/semaphore/db" 9 10 "github.com/ansible-semaphore/semaphore/util" 11 "github.com/gorilla/context" 12 "github.com/masterminds/squirrel" 13) 14 15// EnvironmentMiddleware ensures an environment exists and loads it to the context 16func EnvironmentMiddleware(next http.Handler) http.Handler { 17 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 18 project := context.Get(r, "project").(db.Project) 19 envID, err := util.GetIntParam("environment_id", w, r) 20 if err != nil { 21 return 22 } 23 24 query, args, err := squirrel.Select("*"). 25 From("project__environment"). 26 Where("project_id=?", project.ID). 27 Where("id=?", envID). 28 ToSql() 29 util.LogWarning(err) 30 31 var env db.Environment 32 if err := db.Mysql.SelectOne(&env, query, args...); err != nil { 33 if err == sql.ErrNoRows { 34 w.WriteHeader(http.StatusNotFound) 35 return 36 } 37 38 panic(err) 39 } 40 41 context.Set(r, "environment", env) 42 next.ServeHTTP(w, r) 43 }) 44} 45 46// GetEnvironment retrieves sorted environments from the database 47func GetEnvironment(w http.ResponseWriter, r *http.Request) { 48 if environment := context.Get(r, "environment"); environment != nil { 49 util.WriteJSON(w, http.StatusOK, environment.(db.Environment)) 50 return 51 } 52 53 project := context.Get(r, "project").(db.Project) 54 var env []db.Environment 55 56 sort := r.URL.Query().Get("sort") 57 order := r.URL.Query().Get("order") 58 59 if order != "asc" && order != "desc" { 60 order = "asc" 61 } 62 63 q := squirrel.Select("*"). 64 From("project__environment pe"). 65 Where("project_id=?", project.ID) 66 67 switch sort { 68 case "name": 69 q = q.Where("pe.project_id=?", project.ID). 70 OrderBy("pe." + sort + " " + order) 71 default: 72 q = q.Where("pe.project_id=?", project.ID). 73 OrderBy("pe.name " + order) 74 } 75 76 query, args, err := q.ToSql() 77 util.LogWarning(err) 78 79 if _, err := db.Mysql.Select(&env, query, args...); err != nil { 80 panic(err) 81 } 82 83 util.WriteJSON(w, http.StatusOK, env) 84} 85 86// UpdateEnvironment updates an existing environment in the database 87func UpdateEnvironment(w http.ResponseWriter, r *http.Request) { 88 oldEnv := context.Get(r, "environment").(db.Environment) 89 var env db.Environment 90 if err := util.Bind(w, r, &env); err != nil { 91 return 92 } 93 94 var js map[string]interface{} 95 if json.Unmarshal([]byte(env.JSON), &js) != nil { 96 util.WriteJSON(w, http.StatusBadRequest, map[string]string{ 97 "error": "JSON is not valid", 98 }) 99 return 100 } 101 102 if _, err := db.Mysql.Exec("update project__environment set name=?, json=? where id=?", env.Name, env.JSON, oldEnv.ID); err != nil { 103 panic(err) 104 } 105 106 w.WriteHeader(http.StatusNoContent) 107} 108 109// AddEnvironment creates an environment in the database 110func AddEnvironment(w http.ResponseWriter, r *http.Request) { 111 project := context.Get(r, "project").(db.Project) 112 var env db.Environment 113 114 if err := util.Bind(w, r, &env); err != nil { 115 return 116 } 117 118 var js map[string]interface{} 119 if json.Unmarshal([]byte(env.JSON), &js) != nil { 120 util.WriteJSON(w, http.StatusBadRequest, map[string]string{ 121 "error": "JSON is not valid", 122 }) 123 return 124 } 125 126 res, err := db.Mysql.Exec("insert into project__environment set project_id=?, name=?, json=?, password=?", project.ID, env.Name, env.JSON, env.Password) 127 if err != nil { 128 panic(err) 129 } 130 131 insertID, err := res.LastInsertId() 132 util.LogWarning(err) 133 insertIDInt := int(insertID) 134 objType := "environment" 135 136 desc := "Environment " + env.Name + " created" 137 if err := (db.Event{ 138 ProjectID: &project.ID, 139 ObjectType: &objType, 140 ObjectID: &insertIDInt, 141 Description: &desc, 142 }.Insert()); err != nil { 143 panic(err) 144 } 145 146 w.WriteHeader(http.StatusNoContent) 147} 148 149// RemoveEnvironment deletes an environment from the database 150func RemoveEnvironment(w http.ResponseWriter, r *http.Request) { 151 env := context.Get(r, "environment").(db.Environment) 152 153 templatesC, err := db.Mysql.SelectInt("select count(1) from project__template where project_id=? and environment_id=?", env.ProjectID, env.ID) 154 if err != nil { 155 panic(err) 156 } 157 158 if templatesC > 0 { 159 if len(r.URL.Query().Get("setRemoved")) == 0 { 160 util.WriteJSON(w, http.StatusBadRequest, map[string]interface{}{ 161 "error": "Environment is in use by one or more templates", 162 "inUse": true, 163 }) 164 165 return 166 } 167 168 if _, err := db.Mysql.Exec("update project__environment set removed=1 where id=?", env.ID); err != nil { 169 panic(err) 170 } 171 172 w.WriteHeader(http.StatusNoContent) 173 return 174 } 175 176 if _, err := db.Mysql.Exec("delete from project__environment where id=?", env.ID); err != nil { 177 panic(err) 178 } 179 180 desc := "Environment " + env.Name + " deleted" 181 if err := (db.Event{ 182 ProjectID: &env.ProjectID, 183 Description: &desc, 184 }.Insert()); err != nil { 185 panic(err) 186 } 187 188 w.WriteHeader(http.StatusNoContent) 189} 190