This is an automated email from the git hooks/post-receive script. New commit to branch bow-v2-go in repository bow. See https://gitlab.nuiton.org/chorem/bow.git commit 43ebc196dc1b43bf94a73a9c06ebcd5c2bfe9b35 Author: Benjamin <poussin@codelutin.com> Date: Tue May 26 01:36:15 2020 +0200 rechargement force du user cote back (on garanti d'avoir les bonnes données) le token ne contient plus que l'id refacto du composant de tags (v-model), force la liste des tags dispo --- pkg/constant/const.go | 4 +- pkg/http/router.go | 16 +++++-- pkg/http/userResource.go | 2 +- pkg/utils/jwt.go | 5 +- web/src/components/SearchInput.vue | 24 +++++----- web/src/components/common/TagsInput.vue | 56 ++++++++++++++-------- web/src/components/preferences/MaxResultEditor.vue | 22 +++++---- web/src/components/preferences/TagsEditor.vue | 8 ++-- web/src/main.js | 22 +++++++-- web/src/views/BookmarkEdit.vue | 2 +- web/src/views/Login.vue | 2 +- web/src/views/Preferences.vue | 4 +- 12 files changed, 105 insertions(+), 62 deletions(-) diff --git a/pkg/constant/const.go b/pkg/constant/const.go index 28ed36d..31bf1b6 100644 --- a/pkg/constant/const.go +++ b/pkg/constant/const.go @@ -22,9 +22,9 @@ Token le nom utiliser pour le token dans les cookies et les parameters de query const Token = "bow-token" /* -AuthFields la liste des champs necessaire pour le token d'authentification +AuthFields la liste des champs necessaire pour l'utilisation du user sur le front et la back' */ -var AuthFields = []string{"id", "admin", "login", "creationdate", "maxtagincloud", "maxresult"} +var AuthFields = []string{"id", "admin", "login", "creationdate", "maxtagincloud", "maxresult", "actions"} /* TokenHeader le nom utiliser pour mettre dans le header de requete http (fallback Authorization) diff --git a/pkg/http/router.go b/pkg/http/router.go index 08e4e34..b6e9281 100644 --- a/pkg/http/router.go +++ b/pkg/http/router.go @@ -209,17 +209,23 @@ func authentication(next http.Handler) http.Handler { } else if err != nil { utils.Throw(w, err) return + } else { + // on force le rechargement du user + tmp, err := repository.User(user, user.ID, constant.AuthFields...) + if err != nil { + utils.Throw(w, err) + return + } else { + user = tmp + } } } else { - user = constant.Nobody - } - - log.Printf("User is '%s'\n", user.ID) - if user.ID == constant.Nobody.ID { utils.Throw(w, utils.NewHTTPError("Need authentication", user, 401)) return } + log.Printf("User is '%s'\n", user.ID) + ctx := context.WithValue(r.Context(), constant.User, user) r = r.WithContext(ctx) authStat.Stop() diff --git a/pkg/http/userResource.go b/pkg/http/userResource.go index ee5b317..5dbe105 100644 --- a/pkg/http/userResource.go +++ b/pkg/http/userResource.go @@ -41,7 +41,7 @@ func createAuth(w http.ResponseWriter, r *http.Request) { log.Println("create token", data["email"], id) pseudoUser := model.BowUser{ID: id} - // on ne met plus les actions dans le cookie car il fini par etre trop gros et plus accepte par les navigateur (>4ko) + userJSON, err := repository.UserJSON(pseudoUser, id, constant.AuthFields...) if err != nil { utils.Throw(w, utils.NewHTTPError500(err, pseudoUser)) diff --git a/pkg/utils/jwt.go b/pkg/utils/jwt.go index 30d7f02..ad9ccc4 100644 --- a/pkg/utils/jwt.go +++ b/pkg/utils/jwt.go @@ -60,7 +60,10 @@ func JwtVerify(token string) (model.BowUser, error) { JwtGenerate generate JWT token from information in parameter */ func JwtGenerate(user model.BowUser) (string, error) { - claims, err := sjwt.ToClaims(user) + // on ne garde que l'id vu que le user est rechargé a chaque requete pour etre sur de travail + // avec des données a jour + u := model.BowUser{ID: user.ID} + claims, err := sjwt.ToClaims(u) if err != nil { return "", NewHTTPError500(err, user) } diff --git a/web/src/components/SearchInput.vue b/web/src/components/SearchInput.vue index dede299..15db960 100644 --- a/web/src/components/SearchInput.vue +++ b/web/src/components/SearchInput.vue @@ -3,11 +3,11 @@ <form @submit.prevent="search"> <label> tags: - <TagsInput id="tags" :selected="mTags" :noCreation="true" @keyup.enter="search"></TagsInput> + <TagsInput id="tags" v-model="tags" :availableTags="queryTags" :noCreation="true"></TagsInput> </label> <label> fulltext: - <input type="text" v-model="mFulltext" @keyup.enter="search" /> + <input type="text" v-model="mFulltext" @keyup.enter="searchFulltext" /> </label> </form> <form @submit.prevent="action"> @@ -30,11 +30,10 @@ import TagsInput from '@/components/common/TagsInput' class SearchInput extends Vue { mTags = '' mFulltext = '' - mQuery = '' - search() { - console.log('search', this.mTags, this.mFulltext) - this.changeTagsAndFulltextAndGo(this.mTags, this.mFulltext) + searchFulltext() { + console.log('search', this.mFulltext) + this.changeFulltextAndGo(this.mFulltext) } action() { @@ -47,7 +46,11 @@ class SearchInput extends Vue { return [] } - return Array.isArray(tags) ? [...tags] : [tags] + return Array.isArray(tags) ? tags : [tags] + } + + set tags(newTags) { + this.changeTagsAndGo(newTags) } get fulltext() { @@ -58,12 +61,7 @@ class SearchInput extends Vue { return this.queryInfo.query } - @Watch('tags', { immediate: true, deep: true }) - onTagsChange(tags) { - console.log('onTagsChange SearchInput', tags) - this.mTags = this.tags - } - + // TODO supprimer ce watch faire comme pour les tags mais avec un timer avant le declenchement de la requete de recherche @Watch('fulltext', { immediate: true, deep: true }) onFulltextChange(fulltext) { console.log('onFulltextChange SearchInput', fulltext) diff --git a/web/src/components/common/TagsInput.vue b/web/src/components/common/TagsInput.vue index 65dd562..fb072f0 100644 --- a/web/src/components/common/TagsInput.vue +++ b/web/src/components/common/TagsInput.vue @@ -1,16 +1,19 @@ -/* -props: - noCreation: n'autorise pas la création de nouveau élément (default: false; création autorisée) - limit: le nombre maximum délément autorisé (default: pas de limite) - displayCount: affiche on non le nombre d'occurence du tag (default: false; par d'affichage) - selected: le tableau contenant le résultat de l'édition (contient les tags) -*/ +/* props: noCreation: n'autorise pas la création de nouveau élément (default: false; création autorisée) limit: le +nombre maximum délément autorisé (default: pas de limite) displayCount: affiche on non le nombre d'occurence du tag +(default: false; par d'affichage) value: le tableau initial des tags allTags: tous les tags disponibles emit: input: le +tableau contenant le résultat de l'édition (contient les tags) */ <template> <vue-tags-input class="tags-input" v-model="currentTag" :tags="selectedTags" - @tags-changed="onChange" + @tags-changed=" + (t) => + $emit( + 'input', + t.map((v) => v.text) + ) + " :add-only-from-autocomplete="noCreation" :max-tags="limit" :autocomplete-items="filteredTags" @@ -27,31 +30,46 @@ import VueTagsInput from '@johmun/vue-tags-input' @Component({ name: 'TagsInput', - props: ['noCreation', 'limit', 'displayCount', 'selected'], + props: ['availableTags', 'noCreation', 'limit', 'displayCount', 'value'], components: { VueTagsInput } }) class TagsInput extends Vue { + @Prop availableTags @Prop noCreation @Prop limit @Prop displayCount - @Prop selected + @Prop value key = [13, ',', ';', ' ', '\t'] + allTagsServer = [] - allTags = [] + get allTags() { + if (this.availableTags) { + if (this.availableTags.length > 0 && !this.availableTags[0].text) { + return this.availableTags.map((text) => { + return {text} + }) + } + return this.availableTags + } - currentTag = '' - get selectedTags() { - return this.selected.map(text => {return {text}}) + if (this.allTagsServer.length === 0) { + this.load() + } + + return this.allTagsServer } - onChange(tags) { - // on remplace tous les elements par les nouveaux, pour que le tabeau original venant du parent soit aussi modifié - this.selected.splice.apply(this.selected, [0, Number.MAX_VALUE].concat(tags.map((t) => t.text))) + currentTag = '' + get selectedTags() { + return this.value.map((text) => { + return { text } + }) } get filteredTags() { let lowerCased = this.currentTag.toLowerCase() + console.log('AAAAAAA', this.allTags) return this.allTags.filter((a) => { return a.text.toLowerCase().indexOf(lowerCased) !== -1 }) @@ -61,7 +79,7 @@ class TagsInput extends Vue { this.$fetch.get('/bookmarks/tags?with-count=true').then( (tags) => { console.log('ok', tags) - this.allTags = tags[0].map((text, i) => { + this.allTagsServer = tags[0].map((text, i) => { return { text, count: tags[1][i] } }) }, @@ -74,7 +92,7 @@ class TagsInput extends Vue { beforeMount() { this.load() - console.log('xxxx', this.canCreate, this.limit, this.displayCount, this.selected) + console.log('xxxx', this.allTags, this.canCreate, this.limit, this.displayCount, this.value) } } diff --git a/web/src/components/preferences/MaxResultEditor.vue b/web/src/components/preferences/MaxResultEditor.vue index e5991ae..e67869a 100644 --- a/web/src/components/preferences/MaxResultEditor.vue +++ b/web/src/components/preferences/MaxResultEditor.vue @@ -1,27 +1,32 @@ <template> <div class="max-result-editor"> - <label for="maxresult">Max result</label><input id="maxresult" class="maxresult" v-model="user.maxresult" /> - <button class="save" @click.prevent="save">Save max result</button> + <label for="maxresult">Max result</label><input id="maxresult" class="maxresult" v-model="maxresult" /> <span class="errorMsg">{{ errorMsg }}</span> </div> </template> <script> -import { Component, Prop, Vue } from 'vue-property-decorator' +import { Component, Vue } from 'vue-property-decorator' @Component({ name: 'MaxResultEditor', - props: ['user'], components: {} }) class MaxResultEditor extends Vue { - @Prop user - errorMsg = '' - save() { - this.$fetch.put('/users/current/maxresult', {maxresult: parseInt(this.user.maxresult)}).then( + get maxresult() { + return this.user.maxresult + } + + set maxresult(value) { + let newMaxresult = parseInt(value) + this.$fetch.put('/users/current/maxresult', {maxresult: newMaxresult}).then( () => { + let newUser = {...this.user} + newUser.maxresult = newMaxresult + this.saveUser(newUser) + this.errorMsg = 'saved' }, (err) => { @@ -30,6 +35,7 @@ class MaxResultEditor extends Vue { } ) } + } export default MaxResultEditor diff --git a/web/src/components/preferences/TagsEditor.vue b/web/src/components/preferences/TagsEditor.vue index 4a98184..57efc64 100644 --- a/web/src/components/preferences/TagsEditor.vue +++ b/web/src/components/preferences/TagsEditor.vue @@ -1,9 +1,9 @@ <template> <div class="tags-editor"> <label for="oldTags">Replace</label> - <TagsInput id="oldTags" :selected="oldTags" :noCreation="true" :limit="1" :displayCount="true"></TagsInput> + <TagsInput id="oldTags" v-model="oldTags" :noCreation="true" :limit="1" :displayCount="true"></TagsInput> <label for="newTags">with</label> - <TagsInput id="oldTags" :selected="newTags" :limit="1"></TagsInput> + <TagsInput id="oldTags" v-model="newTags" :limit="1"></TagsInput> <button class="replace" @click.prevent="doAction">replace</button> <span class="errorMsg">{{ errorMsg }}</span> </div> @@ -40,7 +40,7 @@ class TagsEditor extends Vue { this.oldTags = [] this.newTags = [] // on recharge pour avoir le nouveau tag et le bon count - this.load() + // this.load() }, (err) => { console.log('ko', err) @@ -57,7 +57,7 @@ class TagsEditor extends Vue { this.oldTags = [] this.newTags = [] // on recharge pour avoir le bon count - this.load() + // this.load() }, (err) => { console.log('ko', err) diff --git a/web/src/main.js b/web/src/main.js index 45809e9..3fc728c 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -29,6 +29,9 @@ Vue.prototype.$storage = StoreHelper Vue.mixin({ methods: { + saveUser: function(newUser) { + this.$storage.set('bow-user', newUser) + }, go: function(fullQuery) { console.log('go query', fullQuery) @@ -58,12 +61,21 @@ Vue.mixin({ this.go(query) } }, - changeTagsAndFulltextAndGo: function(tags, fulltext) { + changeFulltextAndGo: function(fulltext) { let query = { ...this.currentQuery } - query.first = 0 - query.tags = tags - query.fulltext = fulltext - this.go(query) + if (fulltext !== query.fulltext) { + query.first = 0 + query.fulltext = fulltext + this.go(query) + } + }, + changeTagsAndGo: function(tags) { + let query = { ...this.currentQuery } + if (tags.length !== query.tags.length || !tags.reduce((a, b) => a && query.tags.includes(b), true)) { + query.first = 0 + query.tags = tags + this.go(query) + } }, goFirst: function() { let query = { ...this.currentQuery } diff --git a/web/src/views/BookmarkEdit.vue b/web/src/views/BookmarkEdit.vue index 48c710b..f128373 100644 --- a/web/src/views/BookmarkEdit.vue +++ b/web/src/views/BookmarkEdit.vue @@ -6,7 +6,7 @@ <input type="text" v-model.trim="bookmark.uri" placeholder="add uri" /> <br /> <!-- <span>{{ bookmark.authenticationinfo }}</span> faire afficher une popup de modification de l'objet auth--> <textarea v-model.trim="bookmark.description" placeholder="add description"></textarea> - <TagsInput id="tags" :selected="bookmark.tags"></TagsInput> <!-- <input type="text" v-model.trim="bookmark.tags" /> <br /> --> + <TagsInput id="tags" v-model="bookmark.tags"></TagsInput> <!-- <input type="text" v-model.trim="bookmark.tags" /> <br /> --> <!-- <span>{{ bookmark.lang }}</span> --> <!-- <span>{{ bookmark.owner }}</span> si mon id n'est pas le meme alors c'est le bookmark d'un autre partage par un group --> <label for="private-alias">private alias: diff --git a/web/src/views/Login.vue b/web/src/views/Login.vue index b4a1406..eb03755 100644 --- a/web/src/views/Login.vue +++ b/web/src/views/Login.vue @@ -44,7 +44,7 @@ class Login extends Vue { this.$fetch.post('/users/auth', this.data).then( (user) => { console.log('ok', user) - this.$storage.set('bow-user', user) // tout se recharge dans App.vue, suite a cette modif + this.saveUser(user) // tout se recharge dans App.vue, suite a cette modif if (this.$route.params.nextUrl != null) { this.$router.push(this.$route.params.nextUrl) diff --git a/web/src/views/Preferences.vue b/web/src/views/Preferences.vue index b957322..4a766c3 100644 --- a/web/src/views/Preferences.vue +++ b/web/src/views/Preferences.vue @@ -21,14 +21,14 @@ import TagsEditor from '@/components/preferences/TagsEditor' }) class Preferences extends Vue { errorMsg = '' - user = {} bookmarkletAdd = `javascript:document.location='${location.protocol}//${location.host}/edit/new?uri='+encodeURIComponent(location.href)+'&description='+encodeURIComponent(document.title + '\\n' + (document.getSelection() || ''))` load() { this.$fetch.get('/users/current').then( (user) => { console.log('ok', user) - this.user = user + // on force la mise a jour du user, pour avoir les dernieres infos + this.saveUser(user) }, (err) => { console.log('ko', err) -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.