✨ Better avatar and banner APIs
This commit is contained in:
		
							
								
								
									
										18
									
								
								.idea/workspace.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										18
									
								
								.idea/workspace.xml
									
									
									
										generated
									
									
									
								
							| @@ -4,8 +4,16 @@ | |||||||
|     <option name="autoReloadType" value="ALL" /> |     <option name="autoReloadType" value="ALL" /> | ||||||
|   </component> |   </component> | ||||||
|   <component name="ChangeListManager"> |   <component name="ChangeListManager"> | ||||||
|     <list default="true" id="3fefb2c4-b6f9-466b-a523-53352e8d6f95" name="更改" comment=":arrow_up: Fix notification listen"> |     <list default="true" id="3fefb2c4-b6f9-466b-a523-53352e8d6f95" name="更改" comment=":bug: Fix magic token's foreign key"> | ||||||
|       <change beforePath="$PROJECT_DIR$/pkg/internal/models/accounts.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/models/accounts.go" afterDir="false" /> |       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> | ||||||
|  |       <change beforePath="$PROJECT_DIR$/pkg/internal/server/api/avatar_api.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/server/api/avatar_api.go" afterDir="false" /> | ||||||
|  |       <change beforePath="$PROJECT_DIR$/pkg/internal/server/api/index.go" beforeDir="false" afterPath="$PROJECT_DIR$/pkg/internal/server/api/index.go" afterDir="false" /> | ||||||
|  |       <change beforePath="$PROJECT_DIR$/settings.toml" beforeDir="false" afterPath="$PROJECT_DIR$/settings.toml" afterDir="false" /> | ||||||
|  |       <change beforePath="$PROJECT_DIR$/web/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/web/.gitignore" afterDir="false" /> | ||||||
|  |       <change beforePath="$PROJECT_DIR$/web/.vite/deps/_metadata.json" beforeDir="false" afterPath="$PROJECT_DIR$/web/.vite/deps/_metadata.json" afterDir="false" /> | ||||||
|  |       <change beforePath="$PROJECT_DIR$/web/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/web/package.json" afterDir="false" /> | ||||||
|  |       <change beforePath="$PROJECT_DIR$/web/src/components/NotificationList.vue" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/components/NotificationList.vue" afterDir="false" /> | ||||||
|  |       <change beforePath="$PROJECT_DIR$/web/src/views/dashboard.vue" beforeDir="false" afterPath="$PROJECT_DIR$/web/src/views/dashboard.vue" afterDir="false" /> | ||||||
|     </list> |     </list> | ||||||
|     <option name="SHOW_DIALOG" value="false" /> |     <option name="SHOW_DIALOG" value="false" /> | ||||||
|     <option name="HIGHLIGHT_CONFLICTS" value="true" /> |     <option name="HIGHLIGHT_CONFLICTS" value="true" /> | ||||||
| @@ -59,7 +67,7 @@ | |||||||
|     "nodejs_package_manager_path": "npm", |     "nodejs_package_manager_path": "npm", | ||||||
|     "run.code.analysis.last.selected.profile": "pProject Default", |     "run.code.analysis.last.selected.profile": "pProject Default", | ||||||
|     "settings.editor.selected.configurable": "preferences.pluginManager", |     "settings.editor.selected.configurable": "preferences.pluginManager", | ||||||
|     "ts.external.directory.path": "/Users/littlesheep/Applications/GoLand.app/Contents/plugins/javascript-plugin/jsLanguageServicesImpl/external", |     "ts.external.directory.path": "/Users/littlesheep/Documents/Projects/Hydrogen/Passport/web/node_modules/typescript/lib", | ||||||
|     "vue.rearranger.settings.migration": "true" |     "vue.rearranger.settings.migration": "true" | ||||||
|   }, |   }, | ||||||
|   "keyToStringList": { |   "keyToStringList": { | ||||||
| @@ -143,7 +151,6 @@ | |||||||
|     </option> |     </option> | ||||||
|   </component> |   </component> | ||||||
|   <component name="VcsManagerConfiguration"> |   <component name="VcsManagerConfiguration"> | ||||||
|     <MESSAGE value=":sparkles: Apple push notification services" /> |  | ||||||
|     <MESSAGE value=":bug: Bug fix and fix" /> |     <MESSAGE value=":bug: Bug fix and fix" /> | ||||||
|     <MESSAGE value=":bug: Fix APNs non-production" /> |     <MESSAGE value=":bug: Fix APNs non-production" /> | ||||||
|     <MESSAGE value=":bug: Bug fixes on notification badges for APNs" /> |     <MESSAGE value=":bug: Bug fixes on notification badges for APNs" /> | ||||||
| @@ -168,7 +175,8 @@ | |||||||
|     <MESSAGE value=":sparkles: Recommend app component" /> |     <MESSAGE value=":sparkles: Recommend app component" /> | ||||||
|     <MESSAGE value=":bug: Bug fixes" /> |     <MESSAGE value=":bug: Bug fixes" /> | ||||||
|     <MESSAGE value=":arrow_up: Fix notification listen" /> |     <MESSAGE value=":arrow_up: Fix notification listen" /> | ||||||
|     <option name="LAST_COMMIT_MESSAGE" value=":arrow_up: Fix notification listen" /> |     <MESSAGE value=":bug: Fix magic token's foreign key" /> | ||||||
|  |     <option name="LAST_COMMIT_MESSAGE" value=":bug: Fix magic token's foreign key" /> | ||||||
|   </component> |   </component> | ||||||
|   <component name="VgoProject"> |   <component name="VgoProject"> | ||||||
|     <settings-migrated>true</settings-migrated> |     <settings-migrated>true</settings-migrated> | ||||||
|   | |||||||
| @@ -19,10 +19,6 @@ func setAvatar(c *fiber.Ctx) error { | |||||||
| 	} | 	} | ||||||
| 	user := c.Locals("user").(models.Account) | 	user := c.Locals("user").(models.Account) | ||||||
|  |  | ||||||
| 	if err := exts.EnsureAuthenticated(c); err != nil { |  | ||||||
| 		return err |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	var data struct { | 	var data struct { | ||||||
| 		AttachmentID uint `json:"attachment" validate:"required"` | 		AttachmentID uint `json:"attachment" validate:"required"` | ||||||
| 	} | 	} | ||||||
| @@ -88,3 +84,29 @@ func setBanner(c *fiber.Ctx) error { | |||||||
|  |  | ||||||
| 	return c.SendStatus(fiber.StatusOK) | 	return c.SendStatus(fiber.StatusOK) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func getAvatar(c *fiber.Ctx) error { | ||||||
|  | 	if err := exts.EnsureAuthenticated(c); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	user := c.Locals("user").(models.Account) | ||||||
|  |  | ||||||
|  | 	if content := user.GetAvatar(); content == nil { | ||||||
|  | 		return c.SendStatus(fiber.StatusNotFound) | ||||||
|  | 	} else { | ||||||
|  | 		return c.Redirect(*content, fiber.StatusNotFound) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func getBanner(c *fiber.Ctx) error { | ||||||
|  | 	if err := exts.EnsureAuthenticated(c); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	user := c.Locals("user").(models.Account) | ||||||
|  |  | ||||||
|  | 	if content := user.GetBanner(); content == nil { | ||||||
|  | 		return c.SendStatus(fiber.StatusNotFound) | ||||||
|  | 	} else { | ||||||
|  | 		return c.Redirect(*content, fiber.StatusNotFound) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
| @@ -22,6 +22,8 @@ func MapAPIs(app *fiber.App) { | |||||||
| 		me := api.Group("/users/me").Name("Myself Operations") | 		me := api.Group("/users/me").Name("Myself Operations") | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
|  | 			me.Get("/avatar", getAvatar) | ||||||
|  | 			me.Get("/banner", getBanner) | ||||||
| 			me.Put("/avatar", setAvatar) | 			me.Put("/avatar", setAvatar) | ||||||
| 			me.Put("/banner", setBanner) | 			me.Put("/banner", setBanner) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| id = "passport01" | id = "passport01" | ||||||
| name = "Solarpass" | name = "Solarpass" | ||||||
|  |  | ||||||
| frontend_app = "/passport/web" | frontend_app = "web/dist" | ||||||
|  |  | ||||||
| bind = "0.0.0.0:8444" | bind = "0.0.0.0:8444" | ||||||
| grpc_bind = "0.0.0.0:7444" | grpc_bind = "0.0.0.0:7444" | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								web/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								web/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -28,3 +28,5 @@ coverage | |||||||
| *.sw? | *.sw? | ||||||
|  |  | ||||||
| *.tsbuildinfo | *.tsbuildinfo | ||||||
|  |  | ||||||
|  | .vite | ||||||
| @@ -1,8 +1,85 @@ | |||||||
| { | { | ||||||
|   "hash": "47c7bee8", |   "hash": "8b6d0833", | ||||||
|   "configHash": "9db2f33b", |   "configHash": "9db2f33b", | ||||||
|   "lockfileHash": "e3b0c442", |   "lockfileHash": "f7feab31", | ||||||
|   "browserHash": "0938dccf", |   "browserHash": "0decaeb8", | ||||||
|   "optimized": {}, |   "optimized": { | ||||||
|   "chunks": {} |     "vue": { | ||||||
|  |       "src": "../../node_modules/vue/dist/vue.runtime.esm-bundler.js", | ||||||
|  |       "file": "vue.js", | ||||||
|  |       "fileHash": "1913939b", | ||||||
|  |       "needsInterop": false | ||||||
|  |     }, | ||||||
|  |     "pinia": { | ||||||
|  |       "src": "../../node_modules/pinia/dist/pinia.mjs", | ||||||
|  |       "file": "pinia.js", | ||||||
|  |       "fileHash": "4c101c90", | ||||||
|  |       "needsInterop": false | ||||||
|  |     }, | ||||||
|  |     "vuetify": { | ||||||
|  |       "src": "../../node_modules/vuetify/lib/framework.mjs", | ||||||
|  |       "file": "vuetify.js", | ||||||
|  |       "fileHash": "3ab2542c", | ||||||
|  |       "needsInterop": false | ||||||
|  |     }, | ||||||
|  |     "vuetify/blueprints": { | ||||||
|  |       "src": "../../node_modules/vuetify/lib/blueprints/index.mjs", | ||||||
|  |       "file": "vuetify_blueprints.js", | ||||||
|  |       "fileHash": "b34fe63c", | ||||||
|  |       "needsInterop": false | ||||||
|  |     }, | ||||||
|  |     "vuetify/components": { | ||||||
|  |       "src": "../../node_modules/vuetify/lib/components/index.mjs", | ||||||
|  |       "file": "vuetify_components.js", | ||||||
|  |       "fileHash": "42f8a374", | ||||||
|  |       "needsInterop": false | ||||||
|  |     }, | ||||||
|  |     "vuetify/labs/components": { | ||||||
|  |       "src": "../../node_modules/vuetify/lib/labs/components.mjs", | ||||||
|  |       "file": "vuetify_labs_components.js", | ||||||
|  |       "fileHash": "a46a672a", | ||||||
|  |       "needsInterop": false | ||||||
|  |     }, | ||||||
|  |     "vuetify/directives": { | ||||||
|  |       "src": "../../node_modules/vuetify/lib/directives/index.mjs", | ||||||
|  |       "file": "vuetify_directives.js", | ||||||
|  |       "fileHash": "66c34130", | ||||||
|  |       "needsInterop": false | ||||||
|  |     }, | ||||||
|  |     "vue-router": { | ||||||
|  |       "src": "../../node_modules/vue-router/dist/vue-router.mjs", | ||||||
|  |       "file": "vue-router.js", | ||||||
|  |       "fileHash": "56488480", | ||||||
|  |       "needsInterop": false | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  |   "chunks": { | ||||||
|  |     "chunk-WKTZ3I3B": { | ||||||
|  |       "file": "chunk-WKTZ3I3B.js" | ||||||
|  |     }, | ||||||
|  |     "chunk-XJKCW2PU": { | ||||||
|  |       "file": "chunk-XJKCW2PU.js" | ||||||
|  |     }, | ||||||
|  |     "chunk-VFMM6PD2": { | ||||||
|  |       "file": "chunk-VFMM6PD2.js" | ||||||
|  |     }, | ||||||
|  |     "chunk-XREPMAG4": { | ||||||
|  |       "file": "chunk-XREPMAG4.js" | ||||||
|  |     }, | ||||||
|  |     "chunk-ZUZRGUJJ": { | ||||||
|  |       "file": "chunk-ZUZRGUJJ.js" | ||||||
|  |     }, | ||||||
|  |     "chunk-V6X3YB3T": { | ||||||
|  |       "file": "chunk-V6X3YB3T.js" | ||||||
|  |     }, | ||||||
|  |     "chunk-6CN2GOSH": { | ||||||
|  |       "file": "chunk-6CN2GOSH.js" | ||||||
|  |     }, | ||||||
|  |     "chunk-AYVSL3LM": { | ||||||
|  |       "file": "chunk-AYVSL3LM.js" | ||||||
|  |     }, | ||||||
|  |     "chunk-Q5PGHB6G": { | ||||||
|  |       "file": "chunk-Q5PGHB6G.js" | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
| @@ -14,12 +14,12 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@fontsource/roboto": "^5.0.13", |     "@fontsource/roboto": "^5.0.13", | ||||||
|     "@mdi/font": "^7.4.47", |     "@mdi/font": "^7.4.47", | ||||||
|     "@unocss/reset": "^0.58.9", |     "@unocss/reset": "^0.61.0", | ||||||
|     "dompurify": "^3.1.5", |     "dompurify": "^3.1.5", | ||||||
|     "marked": "^12.0.2", |     "marked": "^12.0.2", | ||||||
|     "pinia": "^2.1.7", |     "pinia": "^2.1.7", | ||||||
|     "universal-cookie": "^7.1.4", |     "universal-cookie": "^7.1.4", | ||||||
|     "unocss": "^0.58.9", |     "unocss": "^0.61.0", | ||||||
|     "vue": "^3.4.30", |     "vue": "^3.4.30", | ||||||
|     "vue-router": "^4.4.0", |     "vue-router": "^4.4.0", | ||||||
|     "vuetify": "^3.6.10" |     "vuetify": "^3.6.10" | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|                    subtitle="There is no more new things for you..." /> |                    subtitle="There is no more new things for you..." /> | ||||||
|     </v-list> |     </v-list> | ||||||
|  |  | ||||||
|     <v-list v-else class="w-[380px]" density="compact" lines="three"> |     <v-list v-else density="compact" lines="three"> | ||||||
|       <v-list-item v-for="(item, idx) in notify.notifications" :key="idx"> |       <v-list-item v-for="(item, idx) in notify.notifications" :key="idx"> | ||||||
|         <template #title>{{ item.subject }}</template> |         <template #title>{{ item.subject }}</template> | ||||||
|         <template #subtitle>{{ item.content }}</template> |         <template #subtitle>{{ item.content }}</template> | ||||||
|   | |||||||
| @@ -1,15 +1,15 @@ | |||||||
| <template> | <template> | ||||||
|   <div> |   <div> | ||||||
|     <v-card> |     <v-card> | ||||||
|       <v-img cover class="bg-grey-lighten-2" :height="240" :src="'/api/avatar/' + id.userinfo.data.banner" /> |       <v-img cover class="bg-grey-lighten-2" :height="240" src="/api/avatar" /> | ||||||
|  |  | ||||||
|       <v-card-text class="flex gap-3.5 px-5 pb-5"> |       <v-card-text class="flex gap-3.5 px-5 pb-5"> | ||||||
|         <v-avatar |         <v-avatar | ||||||
|           color="grey-lighten-2" |           color="grey-lighten-2" | ||||||
|           icon="mdi-account-circle" |           icon="mdi-account-circle" | ||||||
|           class="rounded-card" |           class="rounded-card" | ||||||
|  |           image="/api/banner" | ||||||
|           :size="54" |           :size="54" | ||||||
|           :image="'/api/avatar/' + id.userinfo.data.avatar" |  | ||||||
|         /> |         /> | ||||||
|         <div> |         <div> | ||||||
|           <h1 class="text-2xl cursor-pointer" @click="show.realname = !show.realname">{{ displayName }}</h1> |           <h1 class="text-2xl cursor-pointer" @click="show.realname = !show.realname">{{ displayName }}</h1> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user