0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-06-13 06:48:40 +02:00

Merge remote-tracking branch 'upstream/main' into limit-repo-size

This commit is contained in:
DmitryFrolovTri 2023-06-30 06:07:12 +00:00
commit 9014d9f8cd
No known key found for this signature in database
GPG Key ID: 0FBA4D49377CDDC3
20 changed files with 731 additions and 20 deletions

View File

@ -39,6 +39,7 @@ jobs:
backend:
- "**/*.go"
- "templates/**/*.tmpl"
- "assets/emoji.json"
- "go.mod"
- "go.sum"
- "Makefile"
@ -46,6 +47,7 @@ jobs:
frontend:
- "**/*.js"
- "web_src/**"
- "assets/emoji.json"
- "package.json"
- "package-lock.json"
- "Makefile"

2
assets/emoji.json generated

File diff suppressed because one or more lines are too long

View File

@ -25,7 +25,7 @@ import (
const (
gemojiURL = "https://raw.githubusercontent.com/github/gemoji/master/db/emoji.json"
maxUnicodeVersion = 14
maxUnicodeVersion = 15
)
var flagOut = flag.String("o", "modules/emoji/emoji_data.go", "out")

View File

@ -230,6 +230,7 @@ var GemojiData = Gemoji{
{"\U0001f382", "birthday cake", []string{"birthday"}, "6.0", false},
{"\U0001f9ac", "bison", []string{"bison"}, "13.0", false},
{"\U0001fae6", "biting lip", []string{"biting_lip"}, "14.0", false},
{"\U0001f426\u200d\u2b1b", "black bird", []string{"black_bird"}, "15.0", false},
{"\U0001f408\u200d\u2b1b", "black cat", []string{"black_cat"}, "13.0", false},
{"\u26ab", "black circle", []string{"black_circle"}, "4.1", false},
{"\U0001f3f4", "black flag", []string{"black_flag"}, "7.0", false},
@ -748,6 +749,7 @@ var GemojiData = Gemoji{
{"\U0001f42c", "dolphin", []string{"dolphin", "flipper"}, "6.0", false},
{"\U0001f1e9\U0001f1f2", "flag: Dominica", []string{"dominica"}, "6.0", false},
{"\U0001f1e9\U0001f1f4", "flag: Dominican Republic", []string{"dominican_republic"}, "6.0", false},
{"\U0001facf", "donkey", []string{"donkey"}, "15.0", false},
{"\U0001f6aa", "door", []string{"door"}, "6.0", false},
{"\U0001fae5", "dotted line face", []string{"dotted_line_face"}, "14.0", false},
{"\U0001f369", "doughnut", []string{"doughnut"}, "6.0", false},
@ -982,11 +984,13 @@ var GemojiData = Gemoji{
{"\U0001f4be", "floppy disk", []string{"floppy_disk"}, "6.0", false},
{"\U0001f3b4", "flower playing cards", []string{"flower_playing_cards"}, "6.0", false},
{"\U0001f633", "flushed face", []string{"flushed"}, "6.0", false},
{"\U0001fa88", "flute", []string{"flute"}, "15.0", false},
{"\U0001fab0", "fly", []string{"fly"}, "13.0", false},
{"\U0001f94f", "flying disc", []string{"flying_disc"}, "11.0", false},
{"\U0001f6f8", "flying saucer", []string{"flying_saucer"}, "11.0", false},
{"\U0001f32b\ufe0f", "fog", []string{"fog"}, "7.0", false},
{"\U0001f301", "foggy", []string{"foggy"}, "6.0", false},
{"\U0001faad", "folding hand fan", []string{"folding_hand_fan"}, "15.0", false},
{"\U0001fad5", "fondue", []string{"fondue"}, "13.0", false},
{"\U0001f9b6", "foot", []string{"foot"}, "11.0", true},
{"\U0001f9b6\U0001f3ff", "foot: Dark Skin Tone", []string{"foot_Dark_Skin_Tone"}, "12.0", false},
@ -1054,6 +1058,7 @@ var GemojiData = Gemoji{
{"\U0001f1ec\U0001f1ee", "flag: Gibraltar", []string{"gibraltar"}, "6.0", false},
{"\U0001f381", "wrapped gift", []string{"gift"}, "6.0", false},
{"\U0001f49d", "heart with ribbon", []string{"gift_heart"}, "6.0", false},
{"\U0001fada", "ginger root", []string{"ginger_root"}, "15.0", false},
{"\U0001f992", "giraffe", []string{"giraffe"}, "11.0", false},
{"\U0001f467", "girl", []string{"girl"}, "6.0", true},
{"\U0001f467\U0001f3ff", "girl: Dark Skin Tone", []string{"girl_Dark_Skin_Tone"}, "12.0", false},
@ -1085,6 +1090,7 @@ var GemojiData = Gemoji{
{"\U0001f3cc\U0001f3fe\ufe0f\u200d\u2640\ufe0f", "woman golfing: Medium-Dark Skin Tone", []string{"golfing_woman_Medium-Dark_Skin_Tone"}, "12.0", false},
{"\U0001f3cc\U0001f3fc\ufe0f\u200d\u2640\ufe0f", "woman golfing: Medium-Light Skin Tone", []string{"golfing_woman_Medium-Light_Skin_Tone"}, "12.0", false},
{"\U0001f3cc\U0001f3fd\ufe0f\u200d\u2640\ufe0f", "woman golfing: Medium Skin Tone", []string{"golfing_woman_Medium_Skin_Tone"}, "12.0", false},
{"\U0001fabf", "goose", []string{"goose"}, "15.0", false},
{"\U0001f98d", "gorilla", []string{"gorilla"}, "9.0", false},
{"\U0001f347", "grapes", []string{"grapes"}, "6.0", false},
{"\U0001f1ec\U0001f1f7", "flag: Greece", []string{"greece"}, "6.0", false},
@ -1097,6 +1103,7 @@ var GemojiData = Gemoji{
{"\U0001f1ec\U0001f1f1", "flag: Greenland", []string{"greenland"}, "6.0", false},
{"\U0001f1ec\U0001f1e9", "flag: Grenada", []string{"grenada"}, "6.0", false},
{"\u2755", "white exclamation mark", []string{"grey_exclamation"}, "6.0", false},
{"\U0001fa76", "grey heart", []string{"grey_heart"}, "15.0", false},
{"\u2754", "white question mark", []string{"grey_question"}, "6.0", false},
{"\U0001f62c", "grimacing face", []string{"grimacing"}, "6.1", false},
{"\U0001f601", "beaming face with smiling eyes", []string{"grin"}, "6.0", false},
@ -1129,6 +1136,7 @@ var GemojiData = Gemoji{
{"\U0001f3b8", "guitar", []string{"guitar"}, "6.0", false},
{"\U0001f52b", "water pistol", []string{"gun"}, "6.0", false},
{"\U0001f1ec\U0001f1fe", "flag: Guyana", []string{"guyana"}, "6.0", false},
{"\U0001faae", "hair pick", []string{"hair_pick"}, "15.0", false},
{"\U0001f487", "person getting haircut", []string{"haircut"}, "6.0", true},
{"\U0001f487\U0001f3ff", "person getting haircut: Dark Skin Tone", []string{"haircut_Dark_Skin_Tone"}, "12.0", false},
{"\U0001f487\U0001f3fb", "person getting haircut: Light Skin Tone", []string{"haircut_Light_Skin_Tone"}, "12.0", false},
@ -1253,6 +1261,7 @@ var GemojiData = Gemoji{
{"\U0001f1ed\U0001f1fa", "flag: Hungary", []string{"hungary"}, "6.0", false},
{"\U0001f62f", "hushed face", []string{"hushed"}, "6.1", false},
{"\U0001f6d6", "hut", []string{"hut"}, "13.0", false},
{"\U0001fabb", "hyacinth", []string{"hyacinth"}, "15.0", false},
{"\U0001f368", "ice cream", []string{"ice_cream"}, "6.0", false},
{"\U0001f9ca", "ice", []string{"ice_cube"}, "12.0", false},
{"\U0001f3d2", "ice hockey", []string{"ice_hockey"}, "8.0", false},
@ -1293,6 +1302,7 @@ var GemojiData = Gemoji{
{"\U0001f479", "ogre", []string{"japanese_ogre"}, "6.0", false},
{"\U0001fad9", "jar", []string{"jar"}, "14.0", false},
{"\U0001f456", "jeans", []string{"jeans"}, "6.0", false},
{"\U0001fabc", "jellyfish", []string{"jellyfish"}, "15.0", false},
{"\U0001f1ef\U0001f1ea", "flag: Jersey", []string{"jersey"}, "6.0", false},
{"\U0001f9e9", "puzzle piece", []string{"jigsaw"}, "11.0", false},
{"\U0001f1ef\U0001f1f4", "flag: Jordan", []string{"jordan"}, "6.0", false},
@ -1319,6 +1329,7 @@ var GemojiData = Gemoji{
{"\U0001f511", "key", []string{"key"}, "6.0", false},
{"\u2328\ufe0f", "keyboard", []string{"keyboard"}, "", false},
{"\U0001f51f", "keycap: 10", []string{"keycap_ten"}, "6.0", false},
{"\U0001faaf", "khanda", []string{"khanda"}, "15.0", false},
{"\U0001f6f4", "kick scooter", []string{"kick_scooter"}, "9.0", false},
{"\U0001f458", "kimono", []string{"kimono"}, "6.0", false},
{"\U0001f1f0\U0001f1ee", "flag: Kiribati", []string{"kiribati"}, "6.0", false},
@ -1383,6 +1394,12 @@ var GemojiData = Gemoji{
{"\U0001faf2\U0001f3fe", "leftwards hand: Medium-Dark Skin Tone", []string{"leftwards_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
{"\U0001faf2\U0001f3fc", "leftwards hand: Medium-Light Skin Tone", []string{"leftwards_hand_Medium-Light_Skin_Tone"}, "12.0", false},
{"\U0001faf2\U0001f3fd", "leftwards hand: Medium Skin Tone", []string{"leftwards_hand_Medium_Skin_Tone"}, "12.0", false},
{"\U0001faf7", "leftwards pushing hand", []string{"leftwards_pushing_hand"}, "15.0", true},
{"\U0001faf7\U0001f3ff", "leftwards pushing hand: Dark Skin Tone", []string{"leftwards_pushing_hand_Dark_Skin_Tone"}, "12.0", false},
{"\U0001faf7\U0001f3fb", "leftwards pushing hand: Light Skin Tone", []string{"leftwards_pushing_hand_Light_Skin_Tone"}, "12.0", false},
{"\U0001faf7\U0001f3fe", "leftwards pushing hand: Medium-Dark Skin Tone", []string{"leftwards_pushing_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
{"\U0001faf7\U0001f3fc", "leftwards pushing hand: Medium-Light Skin Tone", []string{"leftwards_pushing_hand_Medium-Light_Skin_Tone"}, "12.0", false},
{"\U0001faf7\U0001f3fd", "leftwards pushing hand: Medium Skin Tone", []string{"leftwards_pushing_hand_Medium_Skin_Tone"}, "12.0", false},
{"\U0001f9b5", "leg", []string{"leg"}, "11.0", true},
{"\U0001f9b5\U0001f3ff", "leg: Dark Skin Tone", []string{"leg_Dark_Skin_Tone"}, "12.0", false},
{"\U0001f9b5\U0001f3fb", "leg: Light Skin Tone", []string{"leg_Light_Skin_Tone"}, "12.0", false},
@ -1398,6 +1415,7 @@ var GemojiData = Gemoji{
{"\u264e", "Libra", []string{"libra"}, "", false},
{"\U0001f1f1\U0001f1fe", "flag: Libya", []string{"libya"}, "6.0", false},
{"\U0001f1f1\U0001f1ee", "flag: Liechtenstein", []string{"liechtenstein"}, "6.0", false},
{"\U0001fa75", "light blue heart", []string{"light_blue_heart"}, "15.0", false},
{"\U0001f688", "light rail", []string{"light_rail"}, "6.0", false},
{"\U0001f517", "link", []string{"link"}, "6.0", false},
{"\U0001f981", "lion", []string{"lion"}, "8.0", false},
@ -1695,6 +1713,7 @@ var GemojiData = Gemoji{
{"\U0001f570\ufe0f", "mantelpiece clock", []string{"mantelpiece_clock"}, "7.0", false},
{"\U0001f9bd", "manual wheelchair", []string{"manual_wheelchair"}, "12.0", false},
{"\U0001f341", "maple leaf", []string{"maple_leaf"}, "6.0", false},
{"\U0001fa87", "maracas", []string{"maracas"}, "15.0", false},
{"\U0001f1f2\U0001f1ed", "flag: Marshall Islands", []string{"marshall_islands"}, "6.0", false},
{"\U0001f94b", "martial arts uniform", []string{"martial_arts_uniform"}, "9.0", false},
{"\U0001f1f2\U0001f1f6", "flag: Martinique", []string{"martinique"}, "6.0", false},
@ -1799,6 +1818,7 @@ var GemojiData = Gemoji{
{"\U0001f1f2\U0001f1f8", "flag: Montserrat", []string{"montserrat"}, "6.0", false},
{"\U0001f314", "waxing gibbous moon", []string{"moon", "waxing_gibbous_moon"}, "6.0", false},
{"\U0001f96e", "moon cake", []string{"moon_cake"}, "11.0", false},
{"\U0001face", "moose", []string{"moose"}, "15.0", false},
{"\U0001f1f2\U0001f1e6", "flag: Morocco", []string{"morocco"}, "6.0", false},
{"\U0001f393", "graduation cap", []string{"mortar_board"}, "6.0", false},
{"\U0001f54c", "mosque", []string{"mosque"}, "8.0", false},
@ -2076,6 +2096,7 @@ var GemojiData = Gemoji{
{"\U0001f6f3\ufe0f", "passenger ship", []string{"passenger_ship"}, "7.0", false},
{"\U0001f6c2", "passport control", []string{"passport_control"}, "6.0", false},
{"\u23f8\ufe0f", "pause button", []string{"pause_button"}, "7.0", false},
{"\U0001fadb", "pea pod", []string{"pea_pod"}, "15.0", false},
{"\u262e\ufe0f", "peace symbol", []string{"peace_symbol"}, "", false},
{"\U0001f351", "peach", []string{"peach"}, "6.0", false},
{"\U0001f99a", "peacock", []string{"peacock"}, "11.0", false},
@ -2085,7 +2106,12 @@ var GemojiData = Gemoji{
{"\u270f\ufe0f", "pencil", []string{"pencil2"}, "", false},
{"\U0001f427", "penguin", []string{"penguin"}, "6.0", false},
{"\U0001f614", "pensive face", []string{"pensive"}, "6.0", false},
{"\U0001f9d1\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands", []string{"people_holding_hands"}, "12.0", false},
{"\U0001f9d1\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands", []string{"people_holding_hands"}, "12.0", true},
{"\U0001f9d1\U0001f3ff\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Dark Skin Tone", []string{"people_holding_hands_Dark_Skin_Tone"}, "12.0", false},
{"\U0001f9d1\U0001f3fb\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Light Skin Tone", []string{"people_holding_hands_Light_Skin_Tone"}, "12.0", false},
{"\U0001f9d1\U0001f3fe\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Medium-Dark Skin Tone", []string{"people_holding_hands_Medium-Dark_Skin_Tone"}, "12.0", false},
{"\U0001f9d1\U0001f3fc\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Medium-Light Skin Tone", []string{"people_holding_hands_Medium-Light_Skin_Tone"}, "12.0", false},
{"\U0001f9d1\U0001f3fd\u200d\U0001f91d\u200d\U0001f9d1", "people holding hands: Medium Skin Tone", []string{"people_holding_hands_Medium_Skin_Tone"}, "12.0", false},
{"\U0001fac2", "people hugging", []string{"people_hugging"}, "13.0", false},
{"\U0001f3ad", "performing arts", []string{"performing_arts"}, "6.0", false},
{"\U0001f623", "persevering face", []string{"persevere"}, "6.0", false},
@ -2194,6 +2220,7 @@ var GemojiData = Gemoji{
{"\U0001f90f\U0001f3fd", "pinching hand: Medium Skin Tone", []string{"pinching_hand_Medium_Skin_Tone"}, "12.0", false},
{"\U0001f34d", "pineapple", []string{"pineapple"}, "6.0", false},
{"\U0001f3d3", "ping pong", []string{"ping_pong"}, "8.0", false},
{"\U0001fa77", "pink heart", []string{"pink_heart"}, "15.0", false},
{"\U0001f3f4\u200d\u2620\ufe0f", "pirate flag", []string{"pirate_flag"}, "11.0", false},
{"\u2653", "Pisces", []string{"pisces"}, "", false},
{"\U0001f1f5\U0001f1f3", "flag: Pitcairn Islands", []string{"pitcairn_islands"}, "6.0", false},
@ -2346,7 +2373,7 @@ var GemojiData = Gemoji{
{"\U0001f4fb", "radio", []string{"radio"}, "6.0", false},
{"\U0001f518", "radio button", []string{"radio_button"}, "6.0", false},
{"\u2622\ufe0f", "radioactive", []string{"radioactive"}, "", false},
{"\U0001f621", "pouting face", []string{"rage", "pout"}, "6.0", false},
{"\U0001f621", "enraged face", []string{"rage", "pout"}, "6.0", false},
{"\U0001f683", "railway car", []string{"railway_car"}, "6.0", false},
{"\U0001f6e4\ufe0f", "railway track", []string{"railway_track"}, "7.0", false},
{"\U0001f308", "rainbow", []string{"rainbow"}, "6.0", false},
@ -2434,6 +2461,12 @@ var GemojiData = Gemoji{
{"\U0001faf1\U0001f3fe", "rightwards hand: Medium-Dark Skin Tone", []string{"rightwards_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
{"\U0001faf1\U0001f3fc", "rightwards hand: Medium-Light Skin Tone", []string{"rightwards_hand_Medium-Light_Skin_Tone"}, "12.0", false},
{"\U0001faf1\U0001f3fd", "rightwards hand: Medium Skin Tone", []string{"rightwards_hand_Medium_Skin_Tone"}, "12.0", false},
{"\U0001faf8", "rightwards pushing hand", []string{"rightwards_pushing_hand"}, "15.0", true},
{"\U0001faf8\U0001f3ff", "rightwards pushing hand: Dark Skin Tone", []string{"rightwards_pushing_hand_Dark_Skin_Tone"}, "12.0", false},
{"\U0001faf8\U0001f3fb", "rightwards pushing hand: Light Skin Tone", []string{"rightwards_pushing_hand_Light_Skin_Tone"}, "12.0", false},
{"\U0001faf8\U0001f3fe", "rightwards pushing hand: Medium-Dark Skin Tone", []string{"rightwards_pushing_hand_Medium-Dark_Skin_Tone"}, "12.0", false},
{"\U0001faf8\U0001f3fc", "rightwards pushing hand: Medium-Light Skin Tone", []string{"rightwards_pushing_hand_Medium-Light_Skin_Tone"}, "12.0", false},
{"\U0001faf8\U0001f3fd", "rightwards pushing hand: Medium Skin Tone", []string{"rightwards_pushing_hand_Medium_Skin_Tone"}, "12.0", false},
{"\U0001f48d", "ring", []string{"ring"}, "6.0", false},
{"\U0001f6df", "ring buoy", []string{"ring_buoy"}, "14.0", false},
{"\U0001fa90", "ringed planet", []string{"ringed_planet"}, "12.0", false},
@ -2566,6 +2599,7 @@ var GemojiData = Gemoji{
{"7\ufe0f\u20e3", "keycap: 7", []string{"seven"}, "", false},
{"\U0001faa1", "sewing needle", []string{"sewing_needle"}, "13.0", false},
{"\U0001f1f8\U0001f1e8", "flag: Seychelles", []string{"seychelles"}, "6.0", false},
{"\U0001fae8", "shaking face", []string{"shaking_face"}, "15.0", false},
{"\U0001f958", "shallow pan of food", []string{"shallow_pan_of_food"}, "", false},
{"\u2618\ufe0f", "shamrock", []string{"shamrock"}, "4.1", false},
{"\U0001f988", "shark", []string{"shark"}, "9.0", false},
@ -3125,7 +3159,9 @@ var GemojiData = Gemoji{
{"\U0001f32c\ufe0f", "wind face", []string{"wind_face"}, "7.0", false},
{"\U0001fa9f", "window", []string{"window"}, "13.0", false},
{"\U0001f377", "wine glass", []string{"wine_glass"}, "6.0", false},
{"\U0001fabd", "wing", []string{"wing"}, "15.0", false},
{"\U0001f609", "winking face", []string{"wink"}, "6.0", false},
{"\U0001f6dc", "wireless", []string{"wireless"}, "15.0", false},
{"\U0001f43a", "wolf", []string{"wolf"}, "6.0", false},
{"\U0001f469", "woman", []string{"woman"}, "6.0", true},
{"\U0001f469\U0001f3ff", "woman: Dark Skin Tone", []string{"woman_Dark_Skin_Tone"}, "12.0", false},
@ -3364,5 +3400,5 @@ var GemojiData = Gemoji{
{"\U0001f9df", "zombie", []string{"zombie"}, "11.0", false},
{"\U0001f9df\u200d\u2642\ufe0f", "man zombie", []string{"zombie_man"}, "11.0", false},
{"\U0001f9df\u200d\u2640\ufe0f", "woman zombie", []string{"zombie_woman"}, "11.0", false},
{"\U0001f4a4", "zzz", []string{"zzz"}, "6.0", false},
{"\U0001f4a4", "ZZZ", []string{"zzz"}, "6.0", false},
}

View File

@ -384,3 +384,9 @@ type NewIssuePinsAllowed struct {
Issues bool `json:"issues"`
PullRequests bool `json:"pull_requests"`
}
// UpdateRepoAvatarUserOption options when updating the repo avatar
type UpdateRepoAvatarOption struct {
// image must be base64 encoded
Image string `json:"image" binding:"Required"`
}

View File

@ -102,3 +102,9 @@ type RenameUserOption struct {
// unique: true
NewName string `json:"new_username" binding:"Required"`
}
// UpdateUserAvatarUserOption options when updating the user avatar
type UpdateUserAvatarOption struct {
// image must be base64 encoded
Image string `json:"image" binding:"Required"`
}

View File

@ -899,6 +899,11 @@ func Routes() *web.Route {
Patch(bind(api.EditHookOption{}), user.EditHook).
Delete(user.DeleteHook)
}, reqWebhooksEnabled())
m.Group("/avatar", func() {
m.Post("", bind(api.UpdateUserAvatarOption{}), user.UpdateAvatar)
m.Delete("", user.DeleteAvatar)
}, reqToken())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryUser), reqToken())
// Repositories (requires repo scope, org scope)
@ -1134,6 +1139,10 @@ func Routes() *web.Route {
m.Get("/languages", reqRepoReader(unit.TypeCode), repo.GetLanguages)
m.Get("/activities/feeds", repo.ListRepoActivityFeeds)
m.Get("/new_pin_allowed", repo.AreNewIssuePinsAllowed)
m.Group("/avatar", func() {
m.Post("", bind(api.UpdateRepoAvatarOption{}), repo.UpdateAvatar)
m.Delete("", repo.DeleteAvatar)
}, reqAdmin(), reqToken())
}, repoAssignment())
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryRepository))
@ -1314,6 +1323,10 @@ func Routes() *web.Route {
Patch(bind(api.EditHookOption{}), org.EditHook).
Delete(org.DeleteHook)
}, reqToken(), reqOrgOwnership(), reqWebhooksEnabled())
m.Group("/avatar", func() {
m.Post("", bind(api.UpdateUserAvatarOption{}), org.UpdateAvatar)
m.Delete("", org.DeleteAvatar)
}, reqToken(), reqOrgOwnership())
m.Get("/activities/feeds", org.ListOrgActivityFeeds)
}, tokenRequiresScopes(auth_model.AccessTokenScopeCategoryOrganization), orgAssignment(true))
m.Group("/teams/{teamid}", func() {

View File

@ -0,0 +1,74 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package org
import (
"encoding/base64"
"net/http"
"code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
user_service "code.gitea.io/gitea/services/user"
)
// UpdateAvatarupdates the Avatar of an Organisation
func UpdateAvatar(ctx *context.APIContext) {
// swagger:operation POST /orgs/{org}/avatar organization orgUpdateAvatar
// ---
// summary: Update Avatar
// produces:
// - application/json
// parameters:
// - name: org
// in: path
// description: name of the organization
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/UpdateUserAvatarOption"
// responses:
// "204":
// "$ref": "#/responses/empty"
form := web.GetForm(ctx).(*api.UpdateUserAvatarOption)
content, err := base64.StdEncoding.DecodeString(form.Image)
if err != nil {
ctx.Error(http.StatusBadRequest, "DecodeImage", err)
return
}
err = user_service.UploadAvatar(ctx.Org.Organization.AsUser(), content)
if err != nil {
ctx.Error(http.StatusInternalServerError, "UploadAvatar", err)
}
ctx.Status(http.StatusNoContent)
}
// DeleteAvatar deletes the Avatar of an Organisation
func DeleteAvatar(ctx *context.APIContext) {
// swagger:operation DELETE /orgs/{org}/avatar organization orgDeleteAvatar
// ---
// summary: Delete Avatar
// produces:
// - application/json
// parameters:
// - name: org
// in: path
// description: name of the organization
// type: string
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
err := user_service.DeleteAvatar(ctx.Org.Organization.AsUser())
if err != nil {
ctx.Error(http.StatusInternalServerError, "DeleteAvatar", err)
}
ctx.Status(http.StatusNoContent)
}

View File

@ -0,0 +1,84 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repo
import (
"encoding/base64"
"net/http"
"code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
repo_service "code.gitea.io/gitea/services/repository"
)
// UpdateVatar updates the Avatar of an Repo
func UpdateAvatar(ctx *context.APIContext) {
// swagger:operation POST /repos/{owner}/{repo}/avatar repository repoUpdateAvatar
// ---
// summary: Update avatar
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/UpdateRepoAvatarOption"
// responses:
// "204":
// "$ref": "#/responses/empty"
form := web.GetForm(ctx).(*api.UpdateRepoAvatarOption)
content, err := base64.StdEncoding.DecodeString(form.Image)
if err != nil {
ctx.Error(http.StatusBadRequest, "DecodeImage", err)
return
}
err = repo_service.UploadAvatar(ctx, ctx.Repo.Repository, content)
if err != nil {
ctx.Error(http.StatusInternalServerError, "UploadAvatar", err)
}
ctx.Status(http.StatusNoContent)
}
// UpdateAvatar deletes the Avatar of an Repo
func DeleteAvatar(ctx *context.APIContext) {
// swagger:operation DELETE /repos/{owner}/{repo}/avatar repository repoDeleteAvatar
// ---
// summary: Delete avatar
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
err := repo_service.DeleteAvatar(ctx, ctx.Repo.Repository)
if err != nil {
ctx.Error(http.StatusInternalServerError, "DeleteAvatar", err)
}
ctx.Status(http.StatusNoContent)
}

View File

@ -181,4 +181,10 @@ type swaggerParameterBodies struct {
// in:body
CreatePushMirrorOption api.CreatePushMirrorOption
// in:body
UpdateUserAvatarOptions api.UpdateUserAvatarOption
// in:body
UpdateRepoAvatarOptions api.UpdateRepoAvatarOption
}

View File

@ -0,0 +1,63 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package user
import (
"encoding/base64"
"net/http"
"code.gitea.io/gitea/modules/context"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
user_service "code.gitea.io/gitea/services/user"
)
// UpdateAvatar updates the Avatar of an User
func UpdateAvatar(ctx *context.APIContext) {
// swagger:operation POST /user/avatar user userUpdateAvatar
// ---
// summary: Update Avatar
// produces:
// - application/json
// parameters:
// - name: body
// in: body
// schema:
// "$ref": "#/definitions/UpdateUserAvatarOption"
// responses:
// "204":
// "$ref": "#/responses/empty"
form := web.GetForm(ctx).(*api.UpdateUserAvatarOption)
content, err := base64.StdEncoding.DecodeString(form.Image)
if err != nil {
ctx.Error(http.StatusBadRequest, "DecodeImage", err)
return
}
err = user_service.UploadAvatar(ctx.Doer, content)
if err != nil {
ctx.Error(http.StatusInternalServerError, "UploadAvatar", err)
}
ctx.Status(http.StatusNoContent)
}
// DeleteAvatar deletes the Avatar of an User
func DeleteAvatar(ctx *context.APIContext) {
// swagger:operation DELETE /user/avatar user userDeleteAvatar
// ---
// summary: Delete Avatar
// produces:
// - application/json
// responses:
// "204":
// "$ref": "#/responses/empty"
err := user_service.DeleteAvatar(ctx.Doer)
if err != nil {
ctx.Error(http.StatusInternalServerError, "DeleteAvatar", err)
}
ctx.Status(http.StatusNoContent)
}

View File

@ -420,7 +420,13 @@ func PackageSettingsPost(ctx *context.Context) {
ctx.Flash.Success(ctx.Tr("packages.settings.delete.success"))
}
ctx.Redirect(ctx.Package.Owner.HomeLink() + "/-/packages")
redirectURL := ctx.Package.Owner.HomeLink() + "/-/packages"
// redirect to the package if there are still versions available
if has, _ := packages_model.ExistVersion(ctx, &packages_model.PackageSearchOptions{PackageID: ctx.Package.Descriptor.Package.ID}); has {
redirectURL = ctx.Package.Descriptor.PackageWebLink()
}
ctx.Redirect(redirectURL)
return
}
}

View File

@ -84,19 +84,17 @@
{{end}}
</div>
{{end}}
{{if .LatestVersions}}
<div class="divider"></div>
<strong>{{.locale.Tr "packages.versions"}} ({{.TotalVersionCount}})</strong>
<a class="ui right" href="{{$.PackageDescriptor.PackageWebLink}}/versions">{{.locale.Tr "packages.versions.view_all"}}</a>
<div class="ui relaxed list">
{{range .LatestVersions}}
<div class="item gt-df">
<a class="gt-f1" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a>
<span class="text small">{{DateTime "short" .CreatedUnix}}</span>
</div>
{{end}}
<div class="divider"></div>
<strong>{{.locale.Tr "packages.versions"}} ({{.TotalVersionCount}})</strong>
<a class="ui right" href="{{$.PackageDescriptor.PackageWebLink}}/versions">{{.locale.Tr "packages.versions.view_all"}}</a>
<div class="ui relaxed list">
{{range .LatestVersions}}
<div class="item gt-df">
<a class="gt-f1" href="{{$.PackageDescriptor.PackageWebLink}}/{{PathEscape .LowerVersion}}">{{.Version}}</a>
<span class="text small">{{DateTime "short" .CreatedUnix}}</span>
</div>
{{end}}
</div>
{{if or .CanWritePackages .HasRepositoryAccess}}
<div class="divider"></div>
<div class="ui relaxed list">

View File

@ -45,8 +45,8 @@
</div>
<div class="inline field">
<label>{{.locale.Tr "repo.visibility"}}</label>
<div class="ui read-only checkbox">
<input type="checkbox" {{if .IsPrivate}}checked{{end}}>
<div class="ui disabled checkbox">
<input type="checkbox" disabled {{if .IsPrivate}}checked{{end}}>
<label>{{.locale.Tr "repo.visibility_helper" | Safe}}</label>
</div>
<span class="help">{{.locale.Tr "repo.fork_visibility_helper"}}</span>

View File

@ -1595,6 +1595,63 @@
}
}
},
"/orgs/{org}/avatar": {
"post": {
"produces": [
"application/json"
],
"tags": [
"organization"
],
"summary": "Update Avatar",
"operationId": "orgUpdateAvatar",
"parameters": [
{
"type": "string",
"description": "name of the organization",
"name": "org",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/UpdateUserAvatarOption"
}
}
],
"responses": {
"204": {
"$ref": "#/responses/empty"
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"organization"
],
"summary": "Delete Avatar",
"operationId": "orgDeleteAvatar",
"parameters": [
{
"type": "string",
"description": "name of the organization",
"name": "org",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"$ref": "#/responses/empty"
}
}
}
},
"/orgs/{org}/hooks": {
"get": {
"produces": [
@ -3174,6 +3231,77 @@
}
}
},
"/repos/{owner}/{repo}/avatar": {
"post": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Update avatar",
"operationId": "repoUpdateAvatar",
"parameters": [
{
"type": "string",
"description": "owner of the repo",
"name": "owner",
"in": "path",
"required": true
},
{
"type": "string",
"description": "name of the repo",
"name": "repo",
"in": "path",
"required": true
},
{
"name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/UpdateRepoAvatarOption"
}
}
],
"responses": {
"204": {
"$ref": "#/responses/empty"
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"repository"
],
"summary": "Delete avatar",
"operationId": "repoDeleteAvatar",
"parameters": [
{
"type": "string",
"description": "owner of the repo",
"name": "owner",
"in": "path",
"required": true
},
{
"type": "string",
"description": "name of the repo",
"name": "repo",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"$ref": "#/responses/empty"
}
}
}
},
"/repos/{owner}/{repo}/branch_protections": {
"get": {
"produces": [
@ -13787,6 +13915,47 @@
}
}
},
"/user/avatar": {
"post": {
"produces": [
"application/json"
],
"tags": [
"user"
],
"summary": "Update Avatar",
"operationId": "userUpdateAvatar",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"$ref": "#/definitions/UpdateUserAvatarOption"
}
}
],
"responses": {
"204": {
"$ref": "#/responses/empty"
}
}
},
"delete": {
"produces": [
"application/json"
],
"tags": [
"user"
],
"summary": "Delete Avatar",
"operationId": "userDeleteAvatar",
"responses": {
"204": {
"$ref": "#/responses/empty"
}
}
}
},
"/user/emails": {
"get": {
"produces": [
@ -21560,6 +21729,30 @@
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"UpdateRepoAvatarOption": {
"description": "UpdateRepoAvatarUserOption options when updating the repo avatar",
"type": "object",
"properties": {
"image": {
"description": "image must be base64 encoded",
"type": "string",
"x-go-name": "Image"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"UpdateUserAvatarOption": {
"description": "UpdateUserAvatarUserOption options when updating the user avatar",
"type": "object",
"properties": {
"image": {
"description": "image must be base64 encoded",
"type": "string",
"x-go-name": "Image"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
},
"User": {
"description": "User represents a user",
"type": "object",
@ -22849,7 +23042,7 @@
"parameterBodies": {
"description": "parameterBodies",
"schema": {
"$ref": "#/definitions/CreatePushMirrorOption"
"$ref": "#/definitions/UpdateRepoAvatarOption"
}
},
"redirect": {

View File

@ -0,0 +1,72 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"encoding/base64"
"net/http"
"os"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestAPIUpdateOrgAvatar(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
// Test what happens if you use a valid image
avatar, err := os.ReadFile("tests/integration/avatar.png")
assert.NoError(t, err)
if err != nil {
assert.FailNow(t, "Unable to open avatar.png")
}
opts := api.UpdateUserAvatarOption{
Image: base64.StdEncoding.EncodeToString(avatar),
}
req := NewRequestWithJSON(t, "POST", "/api/v1/orgs/user3/avatar?token="+token, &opts)
MakeRequest(t, req, http.StatusNoContent)
// Test what happens if you don't have a valid Base64 string
opts = api.UpdateUserAvatarOption{
Image: "Invalid",
}
req = NewRequestWithJSON(t, "POST", "/api/v1/orgs/user3/avatar?token="+token, &opts)
MakeRequest(t, req, http.StatusBadRequest)
// Test what happens if you use a file that is not an image
text, err := os.ReadFile("tests/integration/README.md")
assert.NoError(t, err)
if err != nil {
assert.FailNow(t, "Unable to open README.md")
}
opts = api.UpdateUserAvatarOption{
Image: base64.StdEncoding.EncodeToString(text),
}
req = NewRequestWithJSON(t, "POST", "/api/v1/orgs/user3/avatar?token="+token, &opts)
MakeRequest(t, req, http.StatusInternalServerError)
}
func TestAPIDeleteOrgAvatar(t *testing.T) {
defer tests.PrepareTestEnv(t)()
session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization)
req := NewRequest(t, "DELETE", "/api/v1/orgs/user3/avatar?token="+token)
MakeRequest(t, req, http.StatusNoContent)
}

View File

@ -0,0 +1,76 @@
// Copyright 2018 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"encoding/base64"
"fmt"
"net/http"
"os"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestAPIUpdateRepoAvatar(t *testing.T) {
defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeWriteRepository)
// Test what happens if you use a valid image
avatar, err := os.ReadFile("tests/integration/avatar.png")
assert.NoError(t, err)
if err != nil {
assert.FailNow(t, "Unable to open avatar.png")
}
opts := api.UpdateRepoAvatarOption{
Image: base64.StdEncoding.EncodeToString(avatar),
}
req := NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/avatar?token=%s", repo.OwnerName, repo.Name, token), &opts)
MakeRequest(t, req, http.StatusNoContent)
// Test what happens if you don't have a valid Base64 string
opts = api.UpdateRepoAvatarOption{
Image: "Invalid",
}
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/avatar?token=%s", repo.OwnerName, repo.Name, token), &opts)
MakeRequest(t, req, http.StatusBadRequest)
// Test what happens if you use a file that is not an image
text, err := os.ReadFile("tests/integration/README.md")
assert.NoError(t, err)
if err != nil {
assert.FailNow(t, "Unable to open README.md")
}
opts = api.UpdateRepoAvatarOption{
Image: base64.StdEncoding.EncodeToString(text),
}
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/repos/%s/%s/avatar?token=%s", repo.OwnerName, repo.Name, token), &opts)
MakeRequest(t, req, http.StatusInternalServerError)
}
func TestAPIDeleteRepoAvatar(t *testing.T) {
defer tests.PrepareTestEnv(t)()
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
token := getUserToken(t, user2.LowerName, auth_model.AccessTokenScopeWriteRepository)
req := NewRequest(t, "DELETE", fmt.Sprintf("/api/v1/repos/%s/%s/avatar?token=%s", repo.OwnerName, repo.Name, token))
MakeRequest(t, req, http.StatusNoContent)
}

View File

@ -0,0 +1,72 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"encoding/base64"
"net/http"
"os"
"testing"
auth_model "code.gitea.io/gitea/models/auth"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/tests"
"github.com/stretchr/testify/assert"
)
func TestAPIUpdateUserAvatar(t *testing.T) {
defer tests.PrepareTestEnv(t)()
normalUsername := "user2"
session := loginUser(t, normalUsername)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
// Test what happens if you use a valid image
avatar, err := os.ReadFile("tests/integration/avatar.png")
assert.NoError(t, err)
if err != nil {
assert.FailNow(t, "Unable to open avatar.png")
}
// Test what happens if you don't have a valid Base64 string
opts := api.UpdateUserAvatarOption{
Image: base64.StdEncoding.EncodeToString(avatar),
}
req := NewRequestWithJSON(t, "POST", "/api/v1/user/avatar?token="+token, &opts)
MakeRequest(t, req, http.StatusNoContent)
opts = api.UpdateUserAvatarOption{
Image: "Invalid",
}
req = NewRequestWithJSON(t, "POST", "/api/v1/user/avatar?token="+token, &opts)
MakeRequest(t, req, http.StatusBadRequest)
// Test what happens if you use a file that is not an image
text, err := os.ReadFile("tests/integration/README.md")
assert.NoError(t, err)
if err != nil {
assert.FailNow(t, "Unable to open README.md")
}
opts = api.UpdateUserAvatarOption{
Image: base64.StdEncoding.EncodeToString(text),
}
req = NewRequestWithJSON(t, "POST", "/api/v1/user/avatar?token="+token, &opts)
MakeRequest(t, req, http.StatusInternalServerError)
}
func TestAPIDeleteUserAvatar(t *testing.T) {
defer tests.PrepareTestEnv(t)()
normalUsername := "user2"
session := loginUser(t, normalUsername)
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteUser)
req := NewRequest(t, "DELETE", "/api/v1/user/avatar?token="+token)
MakeRequest(t, req, http.StatusNoContent)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -39,6 +39,10 @@ test('matchEmoji', () => {
expect(matchEmoji('1st_')).toEqual([
'1st_place_medal',
]);
expect(matchEmoji('jellyfis')).toEqual([
'jellyfish',
]);
});
test('matchMention', () => {