Add search
This commit is contained in:
		| @@ -2,7 +2,7 @@ package apiary | |||||||
|  |  | ||||||
| import "fmt" | import "fmt" | ||||||
|  |  | ||||||
| var Version = "v0.1.1" | var Version = "v0.1.2" | ||||||
| var Build string | var Build string | ||||||
|  |  | ||||||
| func FullVersion() string { | func FullVersion() string { | ||||||
|   | |||||||
| @@ -18,6 +18,7 @@ | |||||||
|             <b-nav-item :to="'/'">Home</b-nav-item> |             <b-nav-item :to="'/'">Home</b-nav-item> | ||||||
|             <b-nav-item :to="'/stats'">Stats</b-nav-item> |             <b-nav-item :to="'/stats'">Stats</b-nav-item> | ||||||
|             <b-nav-item :to="'/attempts'">Attempts</b-nav-item> |             <b-nav-item :to="'/attempts'">Attempts</b-nav-item> | ||||||
|  |             <b-nav-item :to="'/search'">Search</b-nav-item> | ||||||
|           </b-navbar-nav> |           </b-navbar-nav> | ||||||
|         </b-collapse> |         </b-collapse> | ||||||
|       </b-navbar> |       </b-navbar> | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
|         hover |         hover | ||||||
|         :items="attempts" |         :items="attempts" | ||||||
|         :fields="fields" |         :fields="fields" | ||||||
|       ></b-table> |       /> | ||||||
|     </p> |     </p> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|   | |||||||
							
								
								
									
										81
									
								
								web/frontend/src/components/SearchResult.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								web/frontend/src/components/SearchResult.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | <template> | ||||||
|  |   <div class="search-result-container"> | ||||||
|  |     <h1>Search</h1> | ||||||
|  |     <b-form @submit="onSubmit"> | ||||||
|  |       <b-form-input v-model="searchString" placeholder="" /> | ||||||
|  |     </b-form> | ||||||
|  |     <b-table | ||||||
|  |       class="search-results-table" | ||||||
|  |       responsive="md" | ||||||
|  |       striped | ||||||
|  |       hover | ||||||
|  |       :items="attempts" | ||||||
|  |       :fields="fields" | ||||||
|  |     /> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script lang="ts"> | ||||||
|  | import { Component, Vue } from 'vue-property-decorator'; | ||||||
|  | import { LoginAttempt } from '@/apiary/apiary'; | ||||||
|  | import { BvTableFieldArray, BvTableFormatterCallback } from 'bootstrap-vue'; | ||||||
|  | import Axios from 'axios'; | ||||||
|  |  | ||||||
|  | @Component | ||||||
|  | export default class SearchResult extends Vue { | ||||||
|  |   attempts: LoginAttempt[]; | ||||||
|  |  | ||||||
|  |   searchString: string; | ||||||
|  |  | ||||||
|  |   constructor() { | ||||||
|  |     super(); | ||||||
|  |     this.attempts = []; | ||||||
|  |     this.searchString = ''; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   fields: BvTableFieldArray = [ | ||||||
|  |     { | ||||||
|  |       key: 'date', | ||||||
|  |       sortable: true, | ||||||
|  |       formatter: (value: string): string => { | ||||||
|  |         const d = new Date(value); | ||||||
|  |         // This seems stupid... | ||||||
|  |         return d.toTimeString().split(' ')[0]; | ||||||
|  |       }, | ||||||
|  |       sortByFormatted: false, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'username', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'password', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'remoteIP', | ||||||
|  |       sortable: true, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       key: 'country', | ||||||
|  |     }, | ||||||
|  |   ]; | ||||||
|  |  | ||||||
|  |   onSubmit(event: Event) { | ||||||
|  |     event.preventDefault(); | ||||||
|  |  | ||||||
|  |     console.log(this.searchString); | ||||||
|  |     const resp = Axios.get<LoginAttempt[]>( | ||||||
|  |       `/api/query?query=${this.searchString}`, | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     resp.then((r) => { | ||||||
|  |       this.attempts = r.data; | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss" scoped> | ||||||
|  | .search-results-table { | ||||||
|  |   margin-top: 50px; | ||||||
|  | } | ||||||
|  | </style> | ||||||
| @@ -4,6 +4,7 @@ import VueRouter, { RouteConfig } from 'vue-router'; | |||||||
| import AttemptList from '@/components/AttemptList.vue'; | import AttemptList from '@/components/AttemptList.vue'; | ||||||
| import Home from '@/components/Home.vue'; | import Home from '@/components/Home.vue'; | ||||||
| import Stats from '@/components/Stats.vue'; | import Stats from '@/components/Stats.vue'; | ||||||
|  | import SearchResult from '@/components/SearchResult.vue'; | ||||||
| import 'bootstrap/dist/css/bootstrap.css'; | import 'bootstrap/dist/css/bootstrap.css'; | ||||||
| import 'bootstrap-vue/dist/bootstrap-vue.css'; | import 'bootstrap-vue/dist/bootstrap-vue.css'; | ||||||
| import '@fontsource/rubik'; | import '@fontsource/rubik'; | ||||||
| @@ -38,6 +39,11 @@ const routes: Array<RouteConfig> = [ | |||||||
|     name: 'Stats', |     name: 'Stats', | ||||||
|     component: Stats, |     component: Stats, | ||||||
|   }, |   }, | ||||||
|  |   { | ||||||
|  |     path: '/search', | ||||||
|  |     name: 'Search', | ||||||
|  |     component: SearchResult, | ||||||
|  |   } | ||||||
| ]; | ]; | ||||||
|  |  | ||||||
| const router = new VueRouter({ | const router = new VueRouter({ | ||||||
|   | |||||||
| @@ -216,24 +216,51 @@ func (s *Server) HandlerQuery(w http.ResponseWriter, r *http.Request) { | |||||||
| 	queryType := r.URL.Query().Get("type") | 	queryType := r.URL.Query().Get("type") | ||||||
| 	query := r.URL.Query().Get("query") | 	query := r.URL.Query().Get("query") | ||||||
|  |  | ||||||
| 	if query == "" || queryType == "" { | 	if query == "" { | ||||||
| 		s.WriteAPIError(w, r, http.StatusBadRequest, "Invalid query or query type") | 		s.WriteAPIError(w, r, http.StatusBadRequest, "Invalid query or query type") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	aq := store.AttemptQuery{ | 	results := []models.LoginAttempt{} | ||||||
| 		QueryType: store.AttemptQueryType(queryType), | 	if queryType == "" { | ||||||
| 		Query:     query, | 		uq := store.AttemptQuery{ | ||||||
| 	} | 			QueryType: store.AttemptQueryType(store.AttemptQueryTypePassword), | ||||||
|  | 			Query:     query, | ||||||
|  | 		} | ||||||
|  | 		pq := store.AttemptQuery{ | ||||||
|  | 			QueryType: store.AttemptQueryType(store.AttemptQueryTypeUsername), | ||||||
|  | 			Query:     query, | ||||||
|  | 		} | ||||||
|  | 		userResults, err := s.store.Query(uq) | ||||||
|  | 		if err != nil { | ||||||
|  | 			s.WriteAPIError(w, r, http.StatusInternalServerError, "Unable to perform query") | ||||||
|  | 			s.ServerLogger.Warnw("Error performing query", "error", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		passwordResults, err := s.store.Query(pq) | ||||||
|  | 		if err != nil { | ||||||
|  | 			s.WriteAPIError(w, r, http.StatusInternalServerError, "Unable to perform query") | ||||||
|  | 			s.ServerLogger.Warnw("Error performing query", "error", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 	results, err := s.store.Query(aq) | 		results = append(results, userResults...) | ||||||
| 	if err != nil { | 		results = append(results, passwordResults...) | ||||||
| 		s.WriteAPIError(w, r, http.StatusInternalServerError, "Unable to perform query") |  | ||||||
| 		s.ServerLogger.Warnw("Error performing query", "error", err) | 	} else { | ||||||
| 		return | 		aq := store.AttemptQuery{ | ||||||
| 	} | 			QueryType: store.AttemptQueryType(queryType), | ||||||
| 	if results == nil { | 			Query:     query, | ||||||
| 		results = []models.LoginAttempt{} | 		} | ||||||
|  |  | ||||||
|  | 		queryResults, err := s.store.Query(aq) | ||||||
|  | 		if err != nil { | ||||||
|  | 			s.WriteAPIError(w, r, http.StatusInternalServerError, "Unable to perform query") | ||||||
|  | 			s.ServerLogger.Warnw("Error performing query", "error", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		results = append(results, queryResults...) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	encoder := json.NewEncoder(w) | 	encoder := json.NewEncoder(w) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user