cmd_users.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  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 console
  11. import (
  12. "encoding/json"
  13. "fmt"
  14. "sort"
  15. "strings"
  16. "devt.de/krotik/common/stringutil"
  17. "devt.de/krotik/eliasdb/api/ac"
  18. )
  19. // Command: users
  20. // ==============
  21. /*
  22. CommandUsers is a command name.
  23. */
  24. const CommandUsers = "users"
  25. /*
  26. CmdUsers returns a list of all users.
  27. */
  28. type CmdUsers struct {
  29. }
  30. /*
  31. Name returns the command name (as it should be typed)
  32. */
  33. func (c *CmdUsers) Name() string {
  34. return CommandUsers
  35. }
  36. /*
  37. ShortDescription returns a short description of the command (single line)
  38. */
  39. func (c *CmdUsers) ShortDescription() string {
  40. return "Returns a list of all users."
  41. }
  42. /*
  43. LongDescription returns an extensive description of the command (can be multiple lines)
  44. */
  45. func (c *CmdUsers) LongDescription() string {
  46. return "Returns a table of all users and their groups."
  47. }
  48. /*
  49. Run executes the command.
  50. */
  51. func (c *CmdUsers) Run(args []string, capi CommandConsoleAPI) error {
  52. res, err := capi.Req(ac.EndpointUser+"u/", "GET", nil)
  53. if err == nil {
  54. var data = res.([]interface{})
  55. var tab []string
  56. tab = append(tab, "Username")
  57. tab = append(tab, "Groups")
  58. for _, d := range data {
  59. u := d.(map[string]interface{})
  60. tab = append(tab, fmt.Sprint(u["username"]))
  61. var groups []string
  62. for _, g := range u["groups"].([]interface{}) {
  63. groups = append(groups, fmt.Sprint(g))
  64. }
  65. tab = append(tab, strings.Join(groups, "/"))
  66. }
  67. capi.ExportBuffer().WriteString(stringutil.PrintCSVTable(tab, 2))
  68. fmt.Fprint(capi.Out(), stringutil.PrintGraphicStringTable(tab, 2, 1,
  69. stringutil.SingleLineTable))
  70. }
  71. return err
  72. }
  73. // Command: groups
  74. // ===============
  75. /*
  76. CommandGroups is a command name.
  77. */
  78. const CommandGroups = "groups"
  79. /*
  80. CmdGroups returns a list of all groups and their permissions.
  81. */
  82. type CmdGroups struct {
  83. }
  84. /*
  85. Name returns the command name (as it should be typed)
  86. */
  87. func (c *CmdGroups) Name() string {
  88. return CommandGroups
  89. }
  90. /*
  91. ShortDescription returns a short description of the command (single line)
  92. */
  93. func (c *CmdGroups) ShortDescription() string {
  94. return "Returns a list of all groups and their permissions."
  95. }
  96. /*
  97. LongDescription returns an extensive description of the command (can be multiple lines)
  98. */
  99. func (c *CmdGroups) LongDescription() string {
  100. return "Returns a list of all groups and their permissions."
  101. }
  102. /*
  103. Run executes the command.
  104. */
  105. func (c *CmdGroups) Run(args []string, capi CommandConsoleAPI) error {
  106. res, err := capi.Req(ac.EndpointUser+"g/", "GET", nil)
  107. if err == nil {
  108. var data = res.(map[string]interface{})
  109. var groups []string
  110. var tab []string
  111. tab = append(tab, "Group")
  112. tab = append(tab, "Path")
  113. tab = append(tab, "Permissions")
  114. for g := range data {
  115. groups = append(groups, g)
  116. }
  117. sort.Strings(groups)
  118. for _, g := range groups {
  119. var paths []string
  120. perms := data[g].(map[string]interface{})
  121. for p := range perms {
  122. paths = append(paths, p)
  123. }
  124. sort.Strings(paths)
  125. if len(paths) > 0 {
  126. for i, p := range paths {
  127. if i == 0 {
  128. tab = append(tab, g)
  129. } else {
  130. tab = append(tab, "")
  131. }
  132. tab = append(tab, p)
  133. tab = append(tab, fmt.Sprint(perms[p]))
  134. }
  135. } else {
  136. tab = append(tab, g)
  137. tab = append(tab, "")
  138. tab = append(tab, "")
  139. }
  140. }
  141. capi.ExportBuffer().WriteString(stringutil.PrintCSVTable(tab, 3))
  142. fmt.Fprint(capi.Out(), stringutil.PrintGraphicStringTable(tab, 3, 1,
  143. stringutil.SingleLineTable))
  144. }
  145. return err
  146. }
  147. // Command: useradd
  148. // ================
  149. /*
  150. CommandUseradd is a command name.
  151. */
  152. const CommandUseradd = "useradd"
  153. /*
  154. CmdUseradd adds a user.
  155. */
  156. type CmdUseradd struct {
  157. }
  158. /*
  159. Name returns the command name (as it should be typed)
  160. */
  161. func (c *CmdUseradd) Name() string {
  162. return CommandUseradd
  163. }
  164. /*
  165. ShortDescription returns a short description of the command (single line)
  166. */
  167. func (c *CmdUseradd) ShortDescription() string {
  168. return "Adds a user to the system."
  169. }
  170. /*
  171. LongDescription returns an extensive description of the command (can be multiple lines)
  172. */
  173. func (c *CmdUseradd) LongDescription() string {
  174. return "Adds a user to the system."
  175. }
  176. /*
  177. Run executes the command.
  178. */
  179. func (c *CmdUseradd) Run(args []string, capi CommandConsoleAPI) error {
  180. if len(args) < 1 {
  181. return fmt.Errorf("Please specify a username")
  182. }
  183. user := args[0]
  184. pass := capi.AskPassword()
  185. data, err := json.Marshal(map[string]interface{}{
  186. "password": pass,
  187. "user_data": map[string]interface{}{},
  188. "group_list": []string{},
  189. })
  190. if err == nil {
  191. _, err = capi.Req(ac.EndpointUser+"u/"+user, "POST", data)
  192. if err == nil {
  193. fmt.Fprintln(capi.Out(), fmt.Sprintf("User %s was created", user))
  194. }
  195. }
  196. return err
  197. }
  198. // Command: newpass
  199. // ================
  200. /*
  201. CommandNewpass is a command name.
  202. */
  203. const CommandNewpass = "newpass"
  204. /*
  205. CmdNewpass changes the password of a user.
  206. */
  207. type CmdNewpass struct {
  208. }
  209. /*
  210. Name returns the command name (as it should be typed)
  211. */
  212. func (c *CmdNewpass) Name() string {
  213. return CommandNewpass
  214. }
  215. /*
  216. ShortDescription returns a short description of the command (single line)
  217. */
  218. func (c *CmdNewpass) ShortDescription() string {
  219. return "Changes the password of a user."
  220. }
  221. /*
  222. LongDescription returns an extensive description of the command (can be multiple lines)
  223. */
  224. func (c *CmdNewpass) LongDescription() string {
  225. return "Changes the password of a user."
  226. }
  227. /*
  228. Run executes the command.
  229. */
  230. func (c *CmdNewpass) Run(args []string, capi CommandConsoleAPI) error {
  231. if len(args) < 1 {
  232. return fmt.Errorf("Please specify a username")
  233. }
  234. user := args[0]
  235. pass := capi.AskPassword()
  236. data, err := json.Marshal(map[string]interface{}{
  237. "password": pass,
  238. })
  239. if err == nil {
  240. _, err = capi.Req(ac.EndpointUser+"u/"+user, "PUT", data)
  241. if err == nil {
  242. fmt.Fprintln(capi.Out(), fmt.Sprintf("Password for user %s was changed", user))
  243. }
  244. }
  245. return err
  246. }
  247. // Command: joingroup
  248. // ==================
  249. /*
  250. CommandJoingroup is a command name.
  251. */
  252. const CommandJoingroup = "joingroup"
  253. /*
  254. CmdJoingroup joins a user to a group.
  255. */
  256. type CmdJoingroup struct {
  257. }
  258. /*
  259. Name returns the command name (as it should be typed)
  260. */
  261. func (c *CmdJoingroup) Name() string {
  262. return CommandJoingroup
  263. }
  264. /*
  265. ShortDescription returns a short description of the command (single line)
  266. */
  267. func (c *CmdJoingroup) ShortDescription() string {
  268. return "Joins a user to a group."
  269. }
  270. /*
  271. LongDescription returns an extensive description of the command (can be multiple lines)
  272. */
  273. func (c *CmdJoingroup) LongDescription() string {
  274. return "Joins a user to a group."
  275. }
  276. /*
  277. Run executes the command.
  278. */
  279. func (c *CmdJoingroup) Run(args []string, capi CommandConsoleAPI) error {
  280. if len(args) < 2 {
  281. return fmt.Errorf("Please specify a username and a group")
  282. }
  283. user := args[0]
  284. group := args[1]
  285. res, err := capi.Req(ac.EndpointUser+"u/"+user, "GET", nil)
  286. if err == nil {
  287. groups := res.(map[string]interface{})["groups"].([]interface{})
  288. for _, g := range groups {
  289. if g == group {
  290. err = fmt.Errorf("User %s is already member of group %s", user, group)
  291. break
  292. }
  293. }
  294. if err == nil {
  295. var data []byte
  296. data, err = json.Marshal(map[string]interface{}{
  297. "group_list": append(groups, group),
  298. })
  299. if err == nil {
  300. _, err = capi.Req(ac.EndpointUser+"u/"+user, "PUT", data)
  301. if err == nil {
  302. fmt.Fprintln(capi.Out(), fmt.Sprintf("User %s has joined group %s", user, group))
  303. }
  304. }
  305. }
  306. }
  307. return err
  308. }
  309. // Command: leavegroup
  310. // ===================
  311. /*
  312. CommandLeavegroup is a command name.
  313. */
  314. const CommandLeavegroup = "leavegroup"
  315. /*
  316. CmdLeavegroup removes a user from a group.
  317. */
  318. type CmdLeavegroup struct {
  319. }
  320. /*
  321. Name returns the command name (as it should be typed)
  322. */
  323. func (c *CmdLeavegroup) Name() string {
  324. return CommandLeavegroup
  325. }
  326. /*
  327. ShortDescription returns a short description of the command (single line)
  328. */
  329. func (c *CmdLeavegroup) ShortDescription() string {
  330. return "Removes a user from a group."
  331. }
  332. /*
  333. LongDescription returns an extensive description of the command (can be multiple lines)
  334. */
  335. func (c *CmdLeavegroup) LongDescription() string {
  336. return "Removes a user from a group."
  337. }
  338. /*
  339. Run executes the command.
  340. */
  341. func (c *CmdLeavegroup) Run(args []string, capi CommandConsoleAPI) error {
  342. if len(args) < 2 {
  343. return fmt.Errorf("Please specify a username and a group")
  344. }
  345. user := args[0]
  346. group := args[1]
  347. res, err := capi.Req(ac.EndpointUser+"u/"+user, "GET", nil)
  348. if err == nil {
  349. var newgroups []interface{}
  350. groups := res.(map[string]interface{})["groups"].([]interface{})
  351. for i, g := range groups {
  352. if g == group {
  353. newgroups = append(groups[:i], groups[i+1:]...)
  354. break
  355. }
  356. }
  357. if newgroups != nil {
  358. var data []byte
  359. data, err = json.Marshal(map[string]interface{}{
  360. "group_list": newgroups,
  361. })
  362. if err == nil {
  363. _, err = capi.Req(ac.EndpointUser+"u/"+user, "PUT", data)
  364. if err == nil {
  365. fmt.Fprintln(capi.Out(), fmt.Sprintf("User %s has left group %s", user, group))
  366. }
  367. }
  368. } else {
  369. err = fmt.Errorf("User %s is not in group %s", user, group)
  370. }
  371. }
  372. return err
  373. }
  374. // Command: userdel
  375. // ================
  376. /*
  377. CommandUserdel is a command name.
  378. */
  379. const CommandUserdel = "userdel"
  380. /*
  381. CmdUserdel deletes a user.
  382. */
  383. type CmdUserdel struct {
  384. }
  385. /*
  386. Name returns the command name (as it should be typed)
  387. */
  388. func (c *CmdUserdel) Name() string {
  389. return CommandUserdel
  390. }
  391. /*
  392. ShortDescription returns a short description of the command (single line)
  393. */
  394. func (c *CmdUserdel) ShortDescription() string {
  395. return "Removes a user from the system."
  396. }
  397. /*
  398. LongDescription returns an extensive description of the command (can be multiple lines)
  399. */
  400. func (c *CmdUserdel) LongDescription() string {
  401. return "Removes a user from the system."
  402. }
  403. /*
  404. Run executes the command.
  405. */
  406. func (c *CmdUserdel) Run(args []string, capi CommandConsoleAPI) error {
  407. if len(args) < 1 {
  408. return fmt.Errorf("Please specify a username")
  409. }
  410. user := args[0]
  411. _, err := capi.Req(ac.EndpointUser+"u/"+user, "DELETE", nil)
  412. if err == nil {
  413. fmt.Fprintln(capi.Out(), fmt.Sprintf("User %s was deleted", user))
  414. }
  415. return err
  416. }
  417. // Command: groupadd
  418. // =================
  419. /*
  420. CommandGroupadd is a command name.
  421. */
  422. const CommandGroupadd = "groupadd"
  423. /*
  424. CmdGroupadd adds a new group.
  425. */
  426. type CmdGroupadd struct {
  427. }
  428. /*
  429. Name returns the command name (as it should be typed)
  430. */
  431. func (c *CmdGroupadd) Name() string {
  432. return CommandGroupadd
  433. }
  434. /*
  435. ShortDescription returns a short description of the command (single line)
  436. */
  437. func (c *CmdGroupadd) ShortDescription() string {
  438. return "Adds a group to the system."
  439. }
  440. /*
  441. LongDescription returns an extensive description of the command (can be multiple lines)
  442. */
  443. func (c *CmdGroupadd) LongDescription() string {
  444. return "Adds a group to the system."
  445. }
  446. /*
  447. Run executes the command.
  448. */
  449. func (c *CmdGroupadd) Run(args []string, capi CommandConsoleAPI) error {
  450. if len(args) < 1 {
  451. return fmt.Errorf("Please specify a groupname")
  452. }
  453. group := args[0]
  454. _, err := capi.Req(ac.EndpointUser+"g/"+group, "POST", nil)
  455. if err == nil {
  456. fmt.Fprintln(capi.Out(), fmt.Sprintf("Group %s was created", group))
  457. }
  458. return err
  459. }
  460. // Command: groupadd
  461. // =================
  462. /*
  463. CommandGroupdel is a command name.
  464. */
  465. const CommandGroupdel = "groupdel"
  466. /*
  467. CmdGroupdel deletes a group.
  468. */
  469. type CmdGroupdel struct {
  470. }
  471. /*
  472. Name returns the command name (as it should be typed)
  473. */
  474. func (c *CmdGroupdel) Name() string {
  475. return CommandGroupdel
  476. }
  477. /*
  478. ShortDescription returns a short description of the command (single line)
  479. */
  480. func (c *CmdGroupdel) ShortDescription() string {
  481. return "Removes a group from the system."
  482. }
  483. /*
  484. LongDescription returns an extensive description of the command (can be multiple lines)
  485. */
  486. func (c *CmdGroupdel) LongDescription() string {
  487. return "Removes a group from the system."
  488. }
  489. /*
  490. Run executes the command.
  491. */
  492. func (c *CmdGroupdel) Run(args []string, capi CommandConsoleAPI) error {
  493. if len(args) < 1 {
  494. return fmt.Errorf("Please specify a groupname")
  495. }
  496. group := args[0]
  497. _, err := capi.Req(ac.EndpointUser+"g/"+group, "DELETE", nil)
  498. if err == nil {
  499. fmt.Fprintln(capi.Out(), fmt.Sprintf("Group %s was deleted", group))
  500. }
  501. return err
  502. }
  503. // Command: grantperm
  504. // ==================
  505. /*
  506. CommandGrantperm is a command name.
  507. */
  508. const CommandGrantperm = "grantperm"
  509. /*
  510. CmdGrantperm grants a new permission to a group.
  511. */
  512. type CmdGrantperm struct {
  513. }
  514. /*
  515. Name returns the command name (as it should be typed)
  516. */
  517. func (c *CmdGrantperm) Name() string {
  518. return CommandGrantperm
  519. }
  520. /*
  521. ShortDescription returns a short description of the command (single line)
  522. */
  523. func (c *CmdGrantperm) ShortDescription() string {
  524. return "Grants a new permission to a group."
  525. }
  526. /*
  527. LongDescription returns an extensive description of the command (can be multiple lines)
  528. */
  529. func (c *CmdGrantperm) LongDescription() string {
  530. return "Grants a new permission to a group. Specify first the permission " +
  531. "in CRUD format (Create, Read, Update or Delete), then a resource path and " +
  532. "then a group name."
  533. }
  534. /*
  535. Run executes the command.
  536. */
  537. func (c *CmdGrantperm) Run(args []string, capi CommandConsoleAPI) error {
  538. if len(args) < 3 {
  539. return fmt.Errorf("Please specify a permission, a resource path and a groupname")
  540. }
  541. perm := args[0]
  542. path := args[1]
  543. group := args[2]
  544. res, err := capi.Req(ac.EndpointUser+"g/"+group, "GET", nil)
  545. if err == nil {
  546. var data []byte
  547. perms := res.(map[string]interface{})
  548. // Merge in new permission
  549. perms[path] = perm
  550. if data, err = json.Marshal(perms); err == nil {
  551. if _, err = capi.Req(ac.EndpointUser+"g/"+group, "PUT", data); err == nil {
  552. fmt.Fprintln(capi.Out(), fmt.Sprintf("Permission %s on %s was granted to %s", perm, path, group))
  553. }
  554. }
  555. }
  556. return err
  557. }
  558. // Command: revokeperm
  559. // ===================
  560. /*
  561. CommandRevokeperm is a command name.
  562. */
  563. const CommandRevokeperm = "revokeperm"
  564. /*
  565. CmdRevokeperm revokes permissions to a resource for a group.
  566. */
  567. type CmdRevokeperm struct {
  568. }
  569. /*
  570. Name returns the command name (as it should be typed)
  571. */
  572. func (c *CmdRevokeperm) Name() string {
  573. return CommandRevokeperm
  574. }
  575. /*
  576. ShortDescription returns a short description of the command (single line)
  577. */
  578. func (c *CmdRevokeperm) ShortDescription() string {
  579. return "Revokes permissions to a resource for a group."
  580. }
  581. /*
  582. LongDescription returns an extensive description of the command (can be multiple lines)
  583. */
  584. func (c *CmdRevokeperm) LongDescription() string {
  585. return "Revokes permissions to a resource for a group."
  586. }
  587. /*
  588. Run executes the command.
  589. */
  590. func (c *CmdRevokeperm) Run(args []string, capi CommandConsoleAPI) error {
  591. if len(args) < 2 {
  592. return fmt.Errorf("Please specify a resource path and a groupname")
  593. }
  594. path := args[0]
  595. group := args[1]
  596. res, err := capi.Req(ac.EndpointUser+"g/"+group, "GET", nil)
  597. if err == nil {
  598. var data []byte
  599. perms := res.(map[string]interface{})
  600. // Merge in new permission
  601. delete(perms, path)
  602. if data, err = json.Marshal(perms); err == nil {
  603. if _, err = capi.Req(ac.EndpointUser+"g/"+group, "PUT", data); err == nil {
  604. fmt.Fprintln(capi.Out(), fmt.Sprintf("All permissions on %s were revoked for %s", path, group))
  605. }
  606. }
  607. }
  608. return err
  609. }