user.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /*
  2. * EliasDB
  3. *
  4. * Copyright 2016 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the Mozilla Public
  7. * License, v. 2.0. If a copy of the MPL was not distributed with this
  8. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. */
  10. package ac
  11. import (
  12. "encoding/json"
  13. "fmt"
  14. "net/http"
  15. "sort"
  16. "devt.de/krotik/common/errorutil"
  17. "devt.de/krotik/common/httputil/access"
  18. "devt.de/krotik/eliasdb/api"
  19. )
  20. /*
  21. EndpointUser is the user endpoint URL (rooted). Handles user/
  22. */
  23. const EndpointUser = api.APIRoot + "/user/"
  24. /*
  25. EndpointWhoAmI is the current user endpoint URL (rooted). Handles whoami/
  26. */
  27. const EndpointWhoAmI = api.APIRoot + "/whoami/"
  28. /*
  29. WhoAmIEndpointInst creates a new endpoint handler.
  30. */
  31. func WhoAmIEndpointInst() api.RestEndpointHandler {
  32. return &whoAmIEndpoint{}
  33. }
  34. /*
  35. Handler object for whoami operations.
  36. */
  37. type whoAmIEndpoint struct {
  38. *api.DefaultEndpointHandler
  39. }
  40. /*
  41. HandleGET handles user queries.
  42. */
  43. func (we *whoAmIEndpoint) HandleGET(w http.ResponseWriter, r *http.Request, resources []string) {
  44. u, ok := AuthHandler.CheckAuth(r)
  45. w.Header().Set("content-type", "application/json; charset=utf-8")
  46. json.NewEncoder(w).Encode(map[string]interface{}{
  47. "username": u,
  48. "logged_in": ok,
  49. })
  50. }
  51. /*
  52. SwaggerDefs is used to describe the endpoint in swagger.
  53. */
  54. func (we *whoAmIEndpoint) SwaggerDefs(s map[string]interface{}) {
  55. s["paths"].(map[string]interface{})["/whoami"] = map[string]interface{}{
  56. "get": map[string]interface{}{
  57. "summary": "Return information about the current user.",
  58. "description": "Returns information about the current user.",
  59. "produces": []string{
  60. "text/plain",
  61. "application/json",
  62. },
  63. "responses": map[string]interface{}{
  64. "200": map[string]interface{}{
  65. "description": "Current user information.",
  66. "schema": map[string]interface{}{
  67. "type": "object",
  68. "properties": map[string]interface{}{
  69. "username": map[string]interface{}{
  70. "description": "Name of the current user.",
  71. "type": "string",
  72. },
  73. "logged_in": map[string]interface{}{
  74. "description": "Flag if the current user is logged in.",
  75. "type": "boolean",
  76. },
  77. },
  78. },
  79. },
  80. "default": map[string]interface{}{
  81. "description": "Error response",
  82. "schema": map[string]interface{}{
  83. "$ref": "#/definitions/Error",
  84. },
  85. },
  86. },
  87. },
  88. }
  89. }
  90. /*
  91. UserEndpointInst creates a new endpoint handler.
  92. */
  93. func UserEndpointInst() api.RestEndpointHandler {
  94. return &userEndpoint{}
  95. }
  96. /*
  97. Handler object for user operations.
  98. */
  99. type userEndpoint struct {
  100. *api.DefaultEndpointHandler
  101. }
  102. /*
  103. HandleGET handles user queries.
  104. */
  105. func (ue *userEndpoint) HandleGET(w http.ResponseWriter, r *http.Request, resources []string) {
  106. var data interface{}
  107. // Check parameters
  108. if !checkResources(w, resources, 1, 2, "Need u or g (user/group) and optionally a name") {
  109. return
  110. }
  111. if resources[0] == "u" {
  112. var userData []map[string]interface{}
  113. dataItem := func(u string) (map[string]interface{}, error) {
  114. ud, ok := UserDB.UserData(u)
  115. if !ok {
  116. return nil, fmt.Errorf("User %s does not exist", u)
  117. }
  118. g, _ := ACL.GroupsOfUser(u)
  119. if g == nil {
  120. g = []string{}
  121. }
  122. return map[string]interface{}{
  123. "username": u,
  124. "groups": g,
  125. "data": ud,
  126. }, nil
  127. }
  128. if len(resources) > 1 {
  129. // Return only a single user
  130. item, err := dataItem(resources[1])
  131. if err != nil {
  132. http.Error(w, err.Error(), http.StatusNotFound)
  133. return
  134. }
  135. w.Header().Set("content-type", "application/json; charset=utf-8")
  136. json.NewEncoder(w).Encode(item)
  137. return
  138. }
  139. users := UserDB.AllUsers()
  140. sort.Strings(users)
  141. for _, u := range users {
  142. item, _ := dataItem(u)
  143. userData = append(userData, item)
  144. }
  145. data = userData
  146. } else if resources[0] == "g" {
  147. groupData, _ := ACL.GetConfig()
  148. if len(resources) > 1 {
  149. var ok bool
  150. groupPerm := groupData["groups"].(map[string]map[string]string)
  151. if data, ok = groupPerm[resources[1]]; !ok {
  152. data = map[string]interface{}{}
  153. }
  154. } else {
  155. data = groupData["groups"]
  156. }
  157. }
  158. // Write data
  159. w.Header().Set("content-type", "application/json; charset=utf-8")
  160. json.NewEncoder(w).Encode(data)
  161. }
  162. /*
  163. HandlePOST handles a REST call to create new users and groups.
  164. */
  165. func (ue *userEndpoint) HandlePOST(w http.ResponseWriter, r *http.Request, resources []string) {
  166. // Check parameters
  167. if !checkResources(w, resources, 2, 2, "Need u or g (user/group) and a name") {
  168. return
  169. }
  170. name := resources[1]
  171. if resources[0] == "u" {
  172. var userDataObject map[string]interface{}
  173. var groupDataObject []interface{}
  174. data := make(map[string]interface{})
  175. dec := json.NewDecoder(r.Body)
  176. if _, ok := UserDB.UserData(name); ok {
  177. // Shortcut the tests if the user already exists
  178. http.Error(w, fmt.Sprintf("Could not add user %s: User %s already exists", name, name),
  179. http.StatusBadRequest)
  180. return
  181. }
  182. if err := dec.Decode(&data); err != nil {
  183. http.Error(w, "Could not decode request body as object: "+err.Error(),
  184. http.StatusBadRequest)
  185. return
  186. }
  187. password, ok := data["password"]
  188. if !ok {
  189. http.Error(w, "Password is missing in body object ", http.StatusBadRequest)
  190. return
  191. }
  192. if userData, ok := data["user_data"]; ok {
  193. if userDataObject, ok = userData.(map[string]interface{}); !ok {
  194. http.Error(w, "User data is not an object", http.StatusBadRequest)
  195. return
  196. }
  197. }
  198. if groupData, ok := data["group_list"]; ok {
  199. if groupDataObject, ok = groupData.([]interface{}); !ok {
  200. http.Error(w, "Group list is not a list", http.StatusBadRequest)
  201. return
  202. }
  203. names, _ := ACL.GroupNames()
  204. for _, g := range groupDataObject {
  205. group := fmt.Sprint(g)
  206. if i := sort.SearchStrings(names, group); !(i < len(names) && names[i] == group) {
  207. http.Error(w, fmt.Sprintf("Group %s does not exist", group), http.StatusBadRequest)
  208. return
  209. }
  210. }
  211. }
  212. if err := UserDB.AddUserEntry(name, fmt.Sprint(password), userDataObject); err != nil {
  213. http.Error(w, fmt.Sprintf("Could not add user %s: %s", name, err.Error()),
  214. http.StatusBadRequest)
  215. return
  216. }
  217. // Add user to various groups
  218. for _, g := range groupDataObject {
  219. ACL.AddUserToGroup(name, fmt.Sprint(g))
  220. }
  221. } else if resources[0] == "g" {
  222. if err := ACL.AddGroup(name); err != nil {
  223. http.Error(w, fmt.Sprintf("Could not add group %s: %s", name, err.Error()),
  224. http.StatusBadRequest)
  225. return
  226. }
  227. } else {
  228. http.Error(w, "Need u or g (user/group) as first path element", http.StatusBadRequest)
  229. return
  230. }
  231. }
  232. /*
  233. HandlePUT handles a REST call to update an existing user or group.
  234. */
  235. func (ue *userEndpoint) HandlePUT(w http.ResponseWriter, r *http.Request, resources []string) {
  236. var err error
  237. // Check parameters
  238. if !checkResources(w, resources, 2, 2, "Need u or g (user/group) and a name") {
  239. return
  240. }
  241. name := resources[1]
  242. if resources[0] == "u" {
  243. var updates []func() error
  244. var userDataObject map[string]interface{}
  245. var groupDataObject []interface{}
  246. if !UserDB.UserExists(name) {
  247. http.Error(w, fmt.Sprintf("User %s does not exist", name), http.StatusBadRequest)
  248. return
  249. }
  250. data := make(map[string]interface{})
  251. dec := json.NewDecoder(r.Body)
  252. if err = dec.Decode(&data); err != nil {
  253. http.Error(w, "Could not decode request body as object: "+err.Error(),
  254. http.StatusBadRequest)
  255. return
  256. }
  257. if passwordObj, ok := data["password"]; ok {
  258. password := fmt.Sprint(passwordObj)
  259. if err = UserDB.IsAcceptablePassword(name, password); err == nil {
  260. updates = append(updates, func() error {
  261. return UserDB.UpdateUserPassword(name, password)
  262. })
  263. }
  264. }
  265. if err == nil {
  266. if userData, ok := data["user_data"]; ok {
  267. if userDataObject, ok = userData.(map[string]interface{}); !ok {
  268. http.Error(w, "User data is not an object", http.StatusBadRequest)
  269. return
  270. }
  271. updates = append(updates, func() error {
  272. return UserDB.UpdateUserData(name, userDataObject)
  273. })
  274. }
  275. if groupData, ok := data["group_list"]; ok {
  276. var userGroups []string
  277. if groupDataObject, ok = groupData.([]interface{}); !ok {
  278. http.Error(w, "Group list is not a list", http.StatusBadRequest)
  279. return
  280. }
  281. userGroups, _ = ACL.GroupsOfUser(name) // Ignore error here if the user does not exist
  282. var names []string
  283. names, err = ACL.GroupNames()
  284. if err == nil {
  285. for _, g := range groupDataObject {
  286. group := fmt.Sprint(g)
  287. if i := sort.SearchStrings(names, group); !(i < len(names) && names[i] == group) {
  288. http.Error(w, fmt.Sprintf("Group %s does not exist", group), http.StatusBadRequest)
  289. return
  290. }
  291. }
  292. // No errors are expected when executing the transaction
  293. for _, g := range userGroups {
  294. errorutil.AssertOk(ACL.RemoveUserFromGroup(name, fmt.Sprint(g)))
  295. }
  296. for _, g := range groupDataObject {
  297. errorutil.AssertOk(ACL.AddUserToGroup(name, fmt.Sprint(g)))
  298. }
  299. }
  300. }
  301. if err == nil {
  302. // Execute the rest of the updates - no errors expected here
  303. for _, f := range updates {
  304. errorutil.AssertOk(f())
  305. }
  306. }
  307. }
  308. } else if resources[0] == "g" {
  309. // Replace all permissions for a given group
  310. if _, err = ACL.Permissions(name); err != nil {
  311. http.Error(w, fmt.Sprintf("Group %s does not exist", name), http.StatusBadRequest)
  312. return
  313. }
  314. data := make(map[string]interface{})
  315. dec := json.NewDecoder(r.Body)
  316. if err = dec.Decode(&data); err != nil {
  317. http.Error(w, "Could not decode request body as object: "+err.Error(),
  318. http.StatusBadRequest)
  319. return
  320. }
  321. for _, perm := range data {
  322. if _, err = access.RightsFromString(fmt.Sprint(perm)); err != nil {
  323. break
  324. }
  325. }
  326. if err == nil {
  327. errorutil.AssertOk(ACL.ClearPermissions(name))
  328. for path, perm := range data {
  329. r, _ := access.RightsFromString(fmt.Sprint(perm))
  330. errorutil.AssertOk(ACL.AddPermission(name, path, r))
  331. }
  332. }
  333. } else {
  334. err = fmt.Errorf("Need u or g (user/group) as first path element")
  335. }
  336. if err != nil {
  337. http.Error(w, err.Error(), http.StatusBadRequest)
  338. }
  339. }
  340. /*
  341. HandleDELETE handles a REST call to remove an existing user or group.
  342. */
  343. func (ue *userEndpoint) HandleDELETE(w http.ResponseWriter, r *http.Request, resources []string) {
  344. // Check parameters
  345. if !checkResources(w, resources, 2, 2, "Need u or g (user/group) and a name") {
  346. return
  347. }
  348. name := resources[1]
  349. if resources[0] == "u" {
  350. if err := UserDB.RemoveUserEntry(name); err != nil {
  351. http.Error(w, fmt.Sprintf("Could not remove user %s: %s", name, err.Error()),
  352. http.StatusBadRequest)
  353. return
  354. }
  355. } else if resources[0] == "g" {
  356. if err := ACL.RemoveGroup(name); err != nil {
  357. http.Error(w, fmt.Sprintf("Could not remove group %s: %s", name, err.Error()),
  358. http.StatusBadRequest)
  359. return
  360. }
  361. } else {
  362. http.Error(w, "Need u or g (user/group) as first path element", http.StatusBadRequest)
  363. return
  364. }
  365. }
  366. /*
  367. SwaggerDefs is used to describe the endpoint in swagger.
  368. */
  369. func (ue *userEndpoint) SwaggerDefs(s map[string]interface{}) {
  370. username := []map[string]interface{}{
  371. map[string]interface{}{
  372. "name": "name",
  373. "in": "path",
  374. "description": "Name of user.",
  375. "required": true,
  376. "type": "string",
  377. },
  378. }
  379. groupname := []map[string]interface{}{
  380. map[string]interface{}{
  381. "name": "name",
  382. "in": "path",
  383. "description": "Name of group.",
  384. "required": true,
  385. "type": "string",
  386. },
  387. }
  388. createParams := []map[string]interface{}{
  389. map[string]interface{}{
  390. "name": "user_creation_data",
  391. "in": "body",
  392. "description": "Additional data to create a user account",
  393. "required": true,
  394. "schema": map[string]interface{}{
  395. "type": "object",
  396. "properties": map[string]interface{}{
  397. "password": map[string]interface{}{
  398. "description": "Password for the new user.",
  399. "type": "string",
  400. },
  401. "user_data": map[string]interface{}{
  402. "description": "Additional user data.",
  403. "type": "object",
  404. },
  405. "group_list": map[string]interface{}{
  406. "description": "List of groups.",
  407. "type": "array",
  408. "items": map[string]interface{}{
  409. "type": "string",
  410. },
  411. },
  412. },
  413. },
  414. },
  415. }
  416. updateParams := []map[string]interface{}{
  417. map[string]interface{}{
  418. "name": "user_update_data",
  419. "in": "body",
  420. "description": "Additional data to update a user account",
  421. "required": true,
  422. "schema": map[string]interface{}{
  423. "type": "object",
  424. "properties": map[string]interface{}{
  425. "password": map[string]interface{}{
  426. "description": "New password for the user.",
  427. "type": "string",
  428. },
  429. "user_data": map[string]interface{}{
  430. "description": "New additional user data.",
  431. "type": "object",
  432. },
  433. "group_list": map[string]interface{}{
  434. "description": "New list of groups.",
  435. "type": "array",
  436. "items": map[string]interface{}{
  437. "type": "string",
  438. },
  439. },
  440. },
  441. },
  442. },
  443. }
  444. permParams := []map[string]interface{}{
  445. map[string]interface{}{
  446. "name": "permission_data",
  447. "in": "body",
  448. "description": "Resource paths and their permissions.",
  449. "required": true,
  450. "schema": map[string]interface{}{
  451. "type": "object",
  452. "properties": map[string]interface{}{
  453. "resource_path": map[string]interface{}{
  454. "description": "Access rights to the resource path as CRUD (create, read, update and delete) string (e.g. '-RU-').",
  455. "type": "string",
  456. "example": "CRUD",
  457. },
  458. },
  459. },
  460. },
  461. }
  462. s["paths"].(map[string]interface{})["/user/u"] = map[string]interface{}{
  463. "get": map[string]interface{}{
  464. "summary": "Return information about all current known users.",
  465. "description": "Returns all registered users.",
  466. "produces": []string{
  467. "text/plain",
  468. "application/json",
  469. },
  470. "responses": map[string]interface{}{
  471. "200": map[string]interface{}{
  472. "description": "List of known users.",
  473. "schema": map[string]interface{}{
  474. "type": "array",
  475. "items": map[string]interface{}{
  476. "type": "object",
  477. "properties": map[string]interface{}{
  478. "username": map[string]interface{}{
  479. "description": "Name of the user.",
  480. "type": "string",
  481. },
  482. "groups": map[string]interface{}{
  483. "description": "Groups of the user.",
  484. "type": "array",
  485. "items": map[string]interface{}{
  486. "type": "string",
  487. },
  488. },
  489. "data": map[string]interface{}{
  490. "description": "Extra data for the user.",
  491. "type": "object",
  492. },
  493. },
  494. },
  495. },
  496. },
  497. "default": map[string]interface{}{
  498. "description": "Error response",
  499. "schema": map[string]interface{}{
  500. "$ref": "#/definitions/Error",
  501. },
  502. },
  503. },
  504. },
  505. }
  506. s["paths"].(map[string]interface{})["/user/g"] = map[string]interface{}{
  507. "get": map[string]interface{}{
  508. "summary": "Return information about all known groups and their permissions.",
  509. "description": "Returns all known groups.",
  510. "produces": []string{
  511. "text/plain",
  512. "application/json",
  513. },
  514. "responses": map[string]interface{}{
  515. "200": map[string]interface{}{
  516. "description": "Known group.",
  517. "schema": map[string]interface{}{
  518. "type": "object",
  519. "properties": map[string]interface{}{
  520. "group_name": map[string]interface{}{
  521. "description": "Resource path.",
  522. "type": "object",
  523. "properties": map[string]interface{}{
  524. "resource_path": map[string]interface{}{
  525. "description": "Access rights to the resource path as CRUD (create, read, update and delete) string (e.g. '-RU-').",
  526. "type": "string",
  527. "example": "CRUD",
  528. },
  529. },
  530. },
  531. },
  532. },
  533. },
  534. "default": map[string]interface{}{
  535. "description": "Error response",
  536. "schema": map[string]interface{}{
  537. "$ref": "#/definitions/Error",
  538. },
  539. },
  540. },
  541. },
  542. }
  543. s["paths"].(map[string]interface{})["/user/u/{name}"] = map[string]interface{}{
  544. "get": map[string]interface{}{
  545. "summary": "Return information about a current known user.",
  546. "description": "Returns a registered user.",
  547. "produces": []string{
  548. "text/plain",
  549. "application/json",
  550. },
  551. "parameters": username,
  552. "responses": map[string]interface{}{
  553. "200": map[string]interface{}{
  554. "description": "Information about a single user.",
  555. "schema": map[string]interface{}{
  556. "type": "object",
  557. "properties": map[string]interface{}{
  558. "username": map[string]interface{}{
  559. "description": "Name of the user.",
  560. "type": "string",
  561. },
  562. "groups": map[string]interface{}{
  563. "description": "Groups of the user.",
  564. "type": "array",
  565. "items": map[string]interface{}{
  566. "type": "string",
  567. },
  568. },
  569. "data": map[string]interface{}{
  570. "description": "Extra data for the user.",
  571. "type": "object",
  572. },
  573. },
  574. },
  575. },
  576. "default": map[string]interface{}{
  577. "description": "Error response",
  578. "schema": map[string]interface{}{
  579. "$ref": "#/definitions/Error",
  580. },
  581. },
  582. },
  583. },
  584. "post": map[string]interface{}{
  585. "summary": "Create a new user.",
  586. "description": "Create a new user.",
  587. "produces": []string{
  588. "text/plain",
  589. "application/json",
  590. },
  591. "parameters": append(username, createParams...),
  592. "responses": map[string]interface{}{
  593. "200": map[string]interface{}{
  594. "description": "Request was successful.",
  595. },
  596. "default": map[string]interface{}{
  597. "description": "Error response",
  598. "schema": map[string]interface{}{
  599. "$ref": "#/definitions/Error",
  600. },
  601. },
  602. },
  603. },
  604. "put": map[string]interface{}{
  605. "summary": "Update an existing user.",
  606. "description": "Update an existing user.",
  607. "produces": []string{
  608. "text/plain",
  609. "application/json",
  610. },
  611. "parameters": append(username, updateParams...),
  612. "responses": map[string]interface{}{
  613. "200": map[string]interface{}{
  614. "description": "Request was successful.",
  615. },
  616. "default": map[string]interface{}{
  617. "description": "Error response",
  618. "schema": map[string]interface{}{
  619. "$ref": "#/definitions/Error",
  620. },
  621. },
  622. },
  623. },
  624. "delete": map[string]interface{}{
  625. "summary": "Delete an existing user.",
  626. "description": "Delete an existing user.",
  627. "produces": []string{
  628. "text/plain",
  629. "application/json",
  630. },
  631. "parameters": username,
  632. "responses": map[string]interface{}{
  633. "200": map[string]interface{}{
  634. "description": "Request was successful.",
  635. },
  636. "default": map[string]interface{}{
  637. "description": "Error response",
  638. "schema": map[string]interface{}{
  639. "$ref": "#/definitions/Error",
  640. },
  641. },
  642. },
  643. },
  644. }
  645. s["paths"].(map[string]interface{})["/user/g/{name}"] = map[string]interface{}{
  646. "get": map[string]interface{}{
  647. "summary": "Return information about a group's permissions.",
  648. "description": "Returns the permissions of a group.",
  649. "produces": []string{
  650. "text/plain",
  651. "application/json",
  652. },
  653. "parameters": groupname,
  654. "responses": map[string]interface{}{
  655. "200": map[string]interface{}{
  656. "description": "Resource paths and their permissions.",
  657. "schema": map[string]interface{}{
  658. "type": "object",
  659. "properties": map[string]interface{}{
  660. "resource_path": map[string]interface{}{
  661. "description": "Access rights to the resource path as CRUD (create, read, update and delete) string (e.g. '-RU-').",
  662. "type": "string",
  663. "example": "CRUD",
  664. },
  665. },
  666. },
  667. },
  668. "default": map[string]interface{}{
  669. "description": "Error response",
  670. "schema": map[string]interface{}{
  671. "$ref": "#/definitions/Error",
  672. },
  673. },
  674. },
  675. },
  676. "post": map[string]interface{}{
  677. "summary": "Create a new group.",
  678. "description": "Create a new group.",
  679. "produces": []string{
  680. "text/plain",
  681. "application/json",
  682. },
  683. "parameters": groupname,
  684. "responses": map[string]interface{}{
  685. "200": map[string]interface{}{
  686. "description": "Request was successful.",
  687. },
  688. "default": map[string]interface{}{
  689. "description": "Error response",
  690. "schema": map[string]interface{}{
  691. "$ref": "#/definitions/Error",
  692. },
  693. },
  694. },
  695. },
  696. "put": map[string]interface{}{
  697. "summary": "Set permissions of an existing group.",
  698. "description": "Set permissions of an existing group.",
  699. "produces": []string{
  700. "text/plain",
  701. "application/json",
  702. },
  703. "parameters": append(groupname, permParams...),
  704. "responses": map[string]interface{}{
  705. "200": map[string]interface{}{
  706. "description": "Request was successful.",
  707. },
  708. "default": map[string]interface{}{
  709. "description": "Error response",
  710. "schema": map[string]interface{}{
  711. "$ref": "#/definitions/Error",
  712. },
  713. },
  714. },
  715. },
  716. "delete": map[string]interface{}{
  717. "summary": "Delete an existing group.",
  718. "description": "Delete an existing group.",
  719. "produces": []string{
  720. "text/plain",
  721. "application/json",
  722. },
  723. "parameters": groupname,
  724. "responses": map[string]interface{}{
  725. "200": map[string]interface{}{
  726. "description": "Request was successful.",
  727. },
  728. "default": map[string]interface{}{
  729. "description": "Error response",
  730. "schema": map[string]interface{}{
  731. "$ref": "#/definitions/Error",
  732. },
  733. },
  734. },
  735. },
  736. }
  737. // Add generic error object to definition
  738. s["definitions"].(map[string]interface{})["Error"] = map[string]interface{}{
  739. "description": "A human readable error mesage.",
  740. "type": "string",
  741. }
  742. }