gitea源码

api_v2.go 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. // Copyright 2022 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package nuget
  4. import (
  5. "encoding/xml"
  6. "strings"
  7. "time"
  8. packages_model "code.gitea.io/gitea/models/packages"
  9. nuget_module "code.gitea.io/gitea/modules/packages/nuget"
  10. )
  11. type AtomTitle struct {
  12. Type string `xml:"type,attr"`
  13. Text string `xml:",chardata"`
  14. }
  15. type ServiceCollection struct {
  16. Href string `xml:"href,attr"`
  17. Title AtomTitle `xml:"atom:title"`
  18. }
  19. type ServiceWorkspace struct {
  20. Title AtomTitle `xml:"atom:title"`
  21. Collection ServiceCollection `xml:"collection"`
  22. }
  23. type ServiceIndexResponseV2 struct {
  24. XMLName xml.Name `xml:"service"`
  25. Base string `xml:"base,attr"`
  26. Xmlns string `xml:"xmlns,attr"`
  27. XmlnsAtom string `xml:"xmlns:atom,attr"`
  28. Workspace ServiceWorkspace `xml:"workspace"`
  29. }
  30. type EdmxPropertyRef struct {
  31. Name string `xml:"Name,attr"`
  32. }
  33. type EdmxProperty struct {
  34. Name string `xml:"Name,attr"`
  35. Type string `xml:"Type,attr"`
  36. Nullable bool `xml:"Nullable,attr"`
  37. }
  38. type EdmxEntityType struct {
  39. Name string `xml:"Name,attr"`
  40. HasStream bool `xml:"m:HasStream,attr"`
  41. Keys []EdmxPropertyRef `xml:"Key>PropertyRef"`
  42. Properties []EdmxProperty `xml:"Property"`
  43. }
  44. type EdmxFunctionParameter struct {
  45. Name string `xml:"Name,attr"`
  46. Type string `xml:"Type,attr"`
  47. }
  48. type EdmxFunctionImport struct {
  49. Name string `xml:"Name,attr"`
  50. ReturnType string `xml:"ReturnType,attr"`
  51. EntitySet string `xml:"EntitySet,attr"`
  52. Parameter []EdmxFunctionParameter `xml:"Parameter"`
  53. }
  54. type EdmxEntitySet struct {
  55. Name string `xml:"Name,attr"`
  56. EntityType string `xml:"EntityType,attr"`
  57. }
  58. type EdmxEntityContainer struct {
  59. Name string `xml:"Name,attr"`
  60. IsDefaultEntityContainer bool `xml:"m:IsDefaultEntityContainer,attr"`
  61. EntitySet EdmxEntitySet `xml:"EntitySet"`
  62. FunctionImports []EdmxFunctionImport `xml:"FunctionImport"`
  63. }
  64. type EdmxSchema struct {
  65. Xmlns string `xml:"xmlns,attr"`
  66. Namespace string `xml:"Namespace,attr"`
  67. EntityType *EdmxEntityType `xml:"EntityType,omitempty"`
  68. EntityContainer *EdmxEntityContainer `xml:"EntityContainer,omitempty"`
  69. }
  70. type EdmxDataServices struct {
  71. XmlnsM string `xml:"xmlns:m,attr"`
  72. DataServiceVersion string `xml:"m:DataServiceVersion,attr"`
  73. MaxDataServiceVersion string `xml:"m:MaxDataServiceVersion,attr"`
  74. Schema []EdmxSchema `xml:"Schema"`
  75. }
  76. type EdmxMetadata struct {
  77. XMLName xml.Name `xml:"edmx:Edmx"`
  78. XmlnsEdmx string `xml:"xmlns:edmx,attr"`
  79. Version string `xml:"Version,attr"`
  80. DataServices EdmxDataServices `xml:"edmx:DataServices"`
  81. }
  82. var Metadata = &EdmxMetadata{
  83. XmlnsEdmx: "http://schemas.microsoft.com/ado/2007/06/edmx",
  84. Version: "1.0",
  85. DataServices: EdmxDataServices{
  86. XmlnsM: "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata",
  87. DataServiceVersion: "2.0",
  88. MaxDataServiceVersion: "2.0",
  89. Schema: []EdmxSchema{
  90. {
  91. Xmlns: "http://schemas.microsoft.com/ado/2006/04/edm",
  92. Namespace: "NuGetGallery.OData",
  93. EntityType: &EdmxEntityType{
  94. Name: "V2FeedPackage",
  95. HasStream: true,
  96. Keys: []EdmxPropertyRef{
  97. {Name: "Id"},
  98. {Name: "Version"},
  99. },
  100. Properties: []EdmxProperty{
  101. {
  102. Name: "Id",
  103. Type: "Edm.String",
  104. },
  105. {
  106. Name: "Version",
  107. Type: "Edm.String",
  108. },
  109. {
  110. Name: "NormalizedVersion",
  111. Type: "Edm.String",
  112. Nullable: true,
  113. },
  114. {
  115. Name: "Authors",
  116. Type: "Edm.String",
  117. Nullable: true,
  118. },
  119. {
  120. Name: "Created",
  121. Type: "Edm.DateTime",
  122. },
  123. {
  124. Name: "Dependencies",
  125. Type: "Edm.String",
  126. },
  127. {
  128. Name: "Description",
  129. Type: "Edm.String",
  130. },
  131. {
  132. Name: "DownloadCount",
  133. Type: "Edm.Int64",
  134. },
  135. {
  136. Name: "LastUpdated",
  137. Type: "Edm.DateTime",
  138. },
  139. {
  140. Name: "Published",
  141. Type: "Edm.DateTime",
  142. },
  143. {
  144. Name: "PackageSize",
  145. Type: "Edm.Int64",
  146. },
  147. {
  148. Name: "ProjectUrl",
  149. Type: "Edm.String",
  150. Nullable: true,
  151. },
  152. {
  153. Name: "ReleaseNotes",
  154. Type: "Edm.String",
  155. Nullable: true,
  156. },
  157. {
  158. Name: "RequireLicenseAcceptance",
  159. Type: "Edm.Boolean",
  160. Nullable: false,
  161. },
  162. {
  163. Name: "Title",
  164. Type: "Edm.String",
  165. Nullable: true,
  166. },
  167. {
  168. Name: "VersionDownloadCount",
  169. Type: "Edm.Int64",
  170. Nullable: false,
  171. },
  172. },
  173. },
  174. },
  175. {
  176. Xmlns: "http://schemas.microsoft.com/ado/2006/04/edm",
  177. Namespace: "NuGetGallery",
  178. EntityContainer: &EdmxEntityContainer{
  179. Name: "V2FeedContext",
  180. IsDefaultEntityContainer: true,
  181. EntitySet: EdmxEntitySet{
  182. Name: "Packages",
  183. EntityType: "NuGetGallery.OData.V2FeedPackage",
  184. },
  185. FunctionImports: []EdmxFunctionImport{
  186. {
  187. Name: "Search",
  188. ReturnType: "Collection(NuGetGallery.OData.V2FeedPackage)",
  189. EntitySet: "Packages",
  190. Parameter: []EdmxFunctionParameter{
  191. {
  192. Name: "searchTerm",
  193. Type: "Edm.String",
  194. },
  195. },
  196. },
  197. {
  198. Name: "FindPackagesById",
  199. ReturnType: "Collection(NuGetGallery.OData.V2FeedPackage)",
  200. EntitySet: "Packages",
  201. Parameter: []EdmxFunctionParameter{
  202. {
  203. Name: "id",
  204. Type: "Edm.String",
  205. },
  206. },
  207. },
  208. },
  209. },
  210. },
  211. },
  212. },
  213. }
  214. type FeedEntryCategory struct {
  215. Term string `xml:"term,attr"`
  216. Scheme string `xml:"scheme,attr"`
  217. }
  218. type FeedEntryLink struct {
  219. Rel string `xml:"rel,attr"`
  220. Href string `xml:"href,attr"`
  221. }
  222. type TypedValue[T any] struct {
  223. Type string `xml:"type,attr,omitempty"`
  224. Value T `xml:",chardata"`
  225. }
  226. type FeedEntryProperties struct {
  227. Authors string `xml:"d:Authors"`
  228. Copyright string `xml:"d:Copyright,omitempty"`
  229. Created TypedValue[time.Time] `xml:"d:Created"`
  230. Dependencies string `xml:"d:Dependencies"`
  231. Description string `xml:"d:Description"`
  232. DevelopmentDependency TypedValue[bool] `xml:"d:DevelopmentDependency"`
  233. DownloadCount TypedValue[int64] `xml:"d:DownloadCount"`
  234. ID string `xml:"d:Id"`
  235. IconURL string `xml:"d:IconUrl,omitempty"`
  236. Language string `xml:"d:Language,omitempty"`
  237. LastUpdated TypedValue[time.Time] `xml:"d:LastUpdated"`
  238. LicenseURL string `xml:"d:LicenseUrl,omitempty"`
  239. MinClientVersion string `xml:"d:MinClientVersion,omitempty"`
  240. NormalizedVersion string `xml:"d:NormalizedVersion"`
  241. Owners string `xml:"d:Owners,omitempty"`
  242. PackageSize TypedValue[int64] `xml:"d:PackageSize"`
  243. ProjectURL string `xml:"d:ProjectUrl,omitempty"`
  244. Published TypedValue[time.Time] `xml:"d:Published"`
  245. ReleaseNotes string `xml:"d:ReleaseNotes,omitempty"`
  246. RequireLicenseAcceptance TypedValue[bool] `xml:"d:RequireLicenseAcceptance"`
  247. Tags string `xml:"d:Tags,omitempty"`
  248. Title string `xml:"d:Title,omitempty"`
  249. Version string `xml:"d:Version"`
  250. VersionDownloadCount TypedValue[int64] `xml:"d:VersionDownloadCount"`
  251. }
  252. type FeedEntry struct {
  253. XMLName xml.Name `xml:"entry"`
  254. Xmlns string `xml:"xmlns,attr,omitempty"`
  255. XmlnsD string `xml:"xmlns:d,attr,omitempty"`
  256. XmlnsM string `xml:"xmlns:m,attr,omitempty"`
  257. Base string `xml:"xml:base,attr,omitempty"`
  258. ID string `xml:"id"`
  259. Category FeedEntryCategory `xml:"category"`
  260. Links []FeedEntryLink `xml:"link"`
  261. Title TypedValue[string] `xml:"title"`
  262. Updated time.Time `xml:"updated"`
  263. Author string `xml:"author>name"`
  264. Summary string `xml:"summary"`
  265. Properties *FeedEntryProperties `xml:"m:properties"`
  266. Content string `xml:",innerxml"`
  267. }
  268. type FeedResponse struct {
  269. XMLName xml.Name `xml:"feed"`
  270. Xmlns string `xml:"xmlns,attr,omitempty"`
  271. XmlnsD string `xml:"xmlns:d,attr,omitempty"`
  272. XmlnsM string `xml:"xmlns:m,attr,omitempty"`
  273. Base string `xml:"xml:base,attr,omitempty"`
  274. ID string `xml:"id"`
  275. Title TypedValue[string] `xml:"title"`
  276. Updated time.Time `xml:"updated"`
  277. Links []FeedEntryLink `xml:"link"`
  278. Entries []*FeedEntry `xml:"entry"`
  279. Count int64 `xml:"m:count"`
  280. }
  281. func createFeedResponse(l *linkBuilder, totalEntries int64, pds []*packages_model.PackageDescriptor) *FeedResponse {
  282. entries := make([]*FeedEntry, 0, len(pds))
  283. for _, pd := range pds {
  284. entries = append(entries, createEntry(l, pd, false))
  285. }
  286. links := []FeedEntryLink{
  287. {Rel: "self", Href: l.Base},
  288. }
  289. if l.Next != nil {
  290. links = append(links, FeedEntryLink{
  291. Rel: "next",
  292. Href: l.GetNextURL(),
  293. })
  294. }
  295. return &FeedResponse{
  296. Xmlns: "http://www.w3.org/2005/Atom",
  297. Base: l.Base,
  298. XmlnsD: "http://schemas.microsoft.com/ado/2007/08/dataservices",
  299. XmlnsM: "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata",
  300. ID: "http://schemas.datacontract.org/2004/07/",
  301. Updated: time.Now(),
  302. Links: links,
  303. Count: totalEntries,
  304. Entries: entries,
  305. }
  306. }
  307. func createEntryResponse(l *linkBuilder, pd *packages_model.PackageDescriptor) *FeedEntry {
  308. return createEntry(l, pd, true)
  309. }
  310. func createEntry(l *linkBuilder, pd *packages_model.PackageDescriptor, withNamespace bool) *FeedEntry {
  311. metadata := pd.Metadata.(*nuget_module.Metadata)
  312. id := l.GetPackageMetadataURL(pd.Package.Name, pd.Version.Version)
  313. // Workaround to force a self-closing tag to satisfy XmlReader.IsEmptyElement used by the NuGet client.
  314. // https://learn.microsoft.com/en-us/dotnet/api/system.xml.xmlreader.isemptyelement
  315. content := `<content type="application/zip" src="` + l.GetPackageDownloadURL(pd.Package.Name, pd.Version.Version) + `"/>`
  316. createdValue := TypedValue[time.Time]{
  317. Type: "Edm.DateTime",
  318. Value: pd.Version.CreatedUnix.AsLocalTime(),
  319. }
  320. entry := &FeedEntry{
  321. ID: id,
  322. Category: FeedEntryCategory{Term: "NuGetGallery.OData.V2FeedPackage", Scheme: "http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"},
  323. Links: []FeedEntryLink{
  324. {Rel: "self", Href: id},
  325. {Rel: "edit", Href: id},
  326. },
  327. Title: TypedValue[string]{Type: "text", Value: pd.Package.Name},
  328. Updated: pd.Version.CreatedUnix.AsLocalTime(),
  329. Author: metadata.Authors,
  330. Content: content,
  331. Properties: &FeedEntryProperties{
  332. Authors: metadata.Authors,
  333. Copyright: metadata.Copyright,
  334. Created: createdValue,
  335. Dependencies: buildDependencyString(metadata),
  336. Description: metadata.Description,
  337. DevelopmentDependency: TypedValue[bool]{Type: "Edm.Boolean", Value: metadata.DevelopmentDependency},
  338. DownloadCount: TypedValue[int64]{Type: "Edm.Int64", Value: pd.Version.DownloadCount},
  339. ID: pd.Package.Name,
  340. IconURL: metadata.IconURL,
  341. Language: metadata.Language,
  342. LastUpdated: createdValue,
  343. LicenseURL: metadata.LicenseURL,
  344. MinClientVersion: metadata.MinClientVersion,
  345. NormalizedVersion: pd.Version.Version,
  346. Owners: metadata.Owners,
  347. PackageSize: TypedValue[int64]{Type: "Edm.Int64", Value: pd.CalculateBlobSize()},
  348. ProjectURL: metadata.ProjectURL,
  349. Published: createdValue,
  350. ReleaseNotes: metadata.ReleaseNotes,
  351. RequireLicenseAcceptance: TypedValue[bool]{Type: "Edm.Boolean", Value: metadata.RequireLicenseAcceptance},
  352. Tags: metadata.Tags,
  353. Title: metadata.Title,
  354. Version: pd.Version.Version,
  355. VersionDownloadCount: TypedValue[int64]{Type: "Edm.Int64", Value: pd.Version.DownloadCount},
  356. },
  357. }
  358. if withNamespace {
  359. entry.Xmlns = "http://www.w3.org/2005/Atom"
  360. entry.Base = l.Base
  361. entry.XmlnsD = "http://schemas.microsoft.com/ado/2007/08/dataservices"
  362. entry.XmlnsM = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"
  363. }
  364. return entry
  365. }
  366. func buildDependencyString(metadata *nuget_module.Metadata) string {
  367. var b strings.Builder
  368. first := true
  369. for group, deps := range metadata.Dependencies {
  370. for _, dep := range deps {
  371. if !first {
  372. b.WriteByte('|')
  373. }
  374. first = false
  375. b.WriteString(dep.ID)
  376. b.WriteByte(':')
  377. b.WriteString(dep.Version)
  378. b.WriteByte(':')
  379. b.WriteString(group)
  380. }
  381. }
  382. return b.String()
  383. }