diff --git a/client/src/api/config.js b/client/src/api/config.js index 6078aeb..bbd0048 100644 --- a/client/src/api/config.js +++ b/client/src/api/config.js @@ -58,6 +58,10 @@ const config = { hostinfo: { type: 'GET', url: `${domain}/hostinfo` + }, + readonly: { + type: 'GET', + url: `${domain}/readonly` } } } diff --git a/client/src/components/side-bar.vue b/client/src/components/side-bar.vue index e9747ce..cc94521 100644 --- a/client/src/components/side-bar.vue +++ b/client/src/components/side-bar.vue @@ -33,12 +33,13 @@ el-menu( //- NOTE: query el-menu-item( + v-if="!$readonly" @click="openQuery" index="-1") i(class="el-icon-edit") span(lot="title") Query - //- NOTE: query + //- NOTE: host info el-menu-item( @click="goHostInfo" index="-2") diff --git a/client/src/components/table-list.vue b/client/src/components/table-list.vue index eb0b32d..ae1b585 100644 --- a/client/src/components/table-list.vue +++ b/client/src/components/table-list.vue @@ -38,11 +38,13 @@ i(class="table-list-icon el-icon-download") span export el-table-column( + v-if="!$readonly" column-key="import" label="import") i(class="table-list-icon el-icon-upload2") span import el-table-column( + v-if="!$readonly" column-key="truncate" label="truncate") i(class="table-list-icon el-icon-folder-delete") diff --git a/client/src/components/table/find/result.vue b/client/src/components/table/find/result.vue index d525fa5..b48870c 100644 --- a/client/src/components/table/find/result.vue +++ b/client/src/components/table/find/result.vue @@ -23,12 +23,14 @@ width="150") el-button-group(slot-scope="scope") el-button( + v-if="!$readonly" type="primary" @click="handleOpenEditDialog(scope.row)" icon="el-icon-edit" size="mini") el-button( + v-if="!$readonly" type="danger" icon="el-icon-delete" size="mini" diff --git a/client/src/components/table/menu.vue b/client/src/components/table/menu.vue index 6691af1..59e92e6 100644 --- a/client/src/components/table/menu.vue +++ b/client/src/components/table/menu.vue @@ -25,11 +25,28 @@ export default { return { defaultActive: get(arr, 5), - tabs: [ - // { - // name: 'rows', - // trigger: this.showRows - // }, + tabs: this.$readonly ? [ + { + name: 'rows', + trigger: this.RowsToken + }, + { + name: 'find', + trigger: this.Find + }, + { + name: 'columns', + trigger: this.Columns + }, + { + name: 'definition', + trigger: this.Definition + }, + { + name: 'export', + trigger: this.Export + } + ] : [ { name: 'rows', trigger: this.RowsToken diff --git a/client/src/components/table/rowstoken.vue b/client/src/components/table/rowstoken.vue index 0188c54..ab634b0 100644 --- a/client/src/components/table/rowstoken.vue +++ b/client/src/components/table/rowstoken.vue @@ -54,12 +54,14 @@ el-button-group(slot-scope="scope") el-button( + v-if="!$readonly" type="primary" @click="handleOpenEditDialog(scope.row)" icon="el-icon-edit" size="mini") el-button( + v-if="!$readonly" type="danger" icon="el-icon-delete" size="mini" diff --git a/client/src/main.js b/client/src/main.js index ca7d833..bc39a21 100644 --- a/client/src/main.js +++ b/client/src/main.js @@ -5,14 +5,32 @@ import '@/plugins/vue-codemirror' import Vue from 'vue'; import App from './App'; import router from './router'; +import api from '@/api' Vue.config.productionTip = false; -/* eslint-disable no-new */ -new Vue({ - el: '#app', - router, - components: { App }, - template: '', - render: h => h(App), -}); +const service = api.make('root') + + +async function init() { + try { + const res = await service.request('readonly') + const ret = res.get() + + Vue.prototype.$readonly = ret.readonly + + /* eslint-disable no-new */ + new Vue({ + el: '#app', + router, + components: { App }, + template: '', + render: h => h(App), + }); + } catch (error) { + // eslint-disable-next-line + console.log(error) + } +} + +init(); diff --git a/service/config.yaml b/service/config.yaml index c0fea7a..0100da2 100644 --- a/service/config.yaml +++ b/service/config.yaml @@ -1,4 +1,5 @@ HOST_PORT: ":8083" +READ_ONLY: false CASSANDRA_HOST: cassandra CASSANDRA_PORT: 9042 diff --git a/service/main.go b/service/main.go index 5f25804..21e84b7 100644 --- a/service/main.go +++ b/service/main.go @@ -24,8 +24,9 @@ import ( ) const ( - PartitionKey = "partition_key" - ClusteringKey = "clustering" + PartitionKey = "partition_key" + ClusteringKey = "clustering" + ReadOnlyMessage = "Update/Insert action are not allowed" ) // init 初始化 @@ -65,6 +66,7 @@ var env envStruct // envStruct type type envStruct struct { HostPort string `mapstructure:"HOST_PORT" json:"HOST_PORT"` + ReadOnly bool `mapstructure:"READ_ONLY" json:"READ_ONLY"` CassandraHost string `mapstructure:"CASSANDRA_HOST" json:"CASSANDRA_HOST"` CassandraPort int `mapstructure:"CASSANDRA_PORT" json:"CASSANDRA_PORT"` CassandraUsername string `mapstructure:"CASSANDRA_USERNAME" json:"CASSANDRA_USERNAME"` @@ -144,7 +146,7 @@ func run(c *cli.Context) { log.Fatal(err) } - h := &Handler{Session: session} + h := &Handler{Session: session, ReadOnly: env.ReadOnly} // Echo instance e := echo.New() @@ -176,17 +178,27 @@ func run(c *cli.Context) { e.GET("/columns", h.Columns) e.GET("/export", h.Export) e.GET("/hostinfo", h.HostInfo) + e.GET("/readonly", h.ReadOnlyInfo) // Start server e.Logger.Fatal(e.Start(env.HostPort)) } type Handler struct { - Session *gocql.Session + Session *gocql.Session + ReadOnly bool +} + +func (h *Handler) ReadOnlyInfo(c echo.Context) error { + return c.JSON(http.StatusOK, map[string]bool{"readonly": h.ReadOnly}) } // Query Query cql語法處理 func (h *Handler) Query(c echo.Context) error { + if h.ReadOnly { + return echo.NewHTTPError(http.StatusForbidden, ReadOnlyMessage) + } + req := struct { Query string `json:"query" form:"query" query:"query"` }{} @@ -346,7 +358,6 @@ func (h *Handler) HostInfo(c echo.Context) error { // RowToken func (h *Handler) RowToken(c echo.Context) error { - var ( req RowTokenReq schema []map[string]interface{} @@ -579,6 +590,10 @@ func (h *Handler) Columns(c echo.Context) error { } func (h *Handler) Save(c echo.Context) error { + if h.ReadOnly { + return echo.NewHTTPError(http.StatusForbidden, ReadOnlyMessage) + } + req := struct { Table string `json:"table" form:"table" query:"table"` Item string `json:"item" form:"item" query:"item"` @@ -624,6 +639,10 @@ func (h *Handler) Save(c echo.Context) error { // Delete 刪除row func (h *Handler) Delete(c echo.Context) error { + if h.ReadOnly { + return echo.NewHTTPError(http.StatusForbidden, ReadOnlyMessage) + } + req := struct { Table string `json:"table" form:"table" query:"table"` Item string `json:"item" form:"item" query:"item"` @@ -860,6 +879,10 @@ func (h *Handler) Export(c echo.Context) error { // Export 匯入copy file func (h *Handler) Import(c echo.Context) error { + if h.ReadOnly { + return echo.NewHTTPError(http.StatusForbidden, ReadOnlyMessage) + } + file, err := c.FormFile("file") table := c.FormValue("table") @@ -928,6 +951,10 @@ func (h *Handler) Import(c echo.Context) error { // Truncate 清除table資料 func (h *Handler) Truncate(c echo.Context) error { + if h.ReadOnly { + return echo.NewHTTPError(http.StatusForbidden, ReadOnlyMessage) + } + req := struct { Table string `json:"table" form:"table" query:"table"` }{}