示例#1
0
        private string GenerateUploadVerifyToken(LFSRequest.LFSObject obj)
        {
            var token = new UploadVerifyToken()
            {
                Oid  = obj.Oid,
                Size = obj.Size
            };

            var value = JsonSerializer.Serialize(token);

            return(dataProtector.Protect(value, UploadTokenValidTime));
        }
示例#2
0
        private async ValueTask <LFSResponse.LFSObject> HandleUpload(LfsProject project, LFSRequest.LFSObject obj)
        {
            var existingObject = await database.LfsObjects
                                 .Where(o => o.LfsOid == obj.Oid && o.LfsProjectId == project.Id).Include(o => o.LfsProject)
                                 .FirstOrDefaultAsync();

            if (existingObject != null)
            {
                // We already have this object
                return(new LFSResponse.LFSObject(obj.Oid, obj.Size)
                {
                    Actions = null,
                    Authenticated = null
                });
            }

            if (obj.Size > AppInfo.MaxLfsUploadSize)
            {
                return(new LFSResponse.LFSObject(obj.Oid, obj.Size,
                                                 new LFSResponse.LFSObject.ErrorInfo(StatusCodes.Status422UnprocessableEntity, "File is too large")));
            }

            logger.LogTrace("Requesting auth because new object is to be uploaded {Oid} for project {Name}", obj.Oid,
                            project.Name);

            // New object. User must have write access
            if (!RequireWriteAccess(out var result))
            {
                throw new InvalidAccessException(result !);
            }

            // We don't yet create the LfsObject here to guard against upload failures
            // instead the verify callback does that

            // The uploads prefix is used here to ensure the user can't overwrite the file after uploading and
            // verification
            var storagePath = "uploads/" + LfsDownloadUrls.OidStoragePath(project, obj.Oid);

            if (!bucketChecked)
            {
                try
                {
                    if (!await remoteStorage.BucketExists())
                    {
                        throw new Exception("bucket doesn't exist");
                    }
                }
                catch (Exception e)
                {
                    logger.LogWarning("Bucket check failed: {@E}", e);
                    var error = "remote storage is inaccessible";
                    throw new HttpResponseException()
                          {
                              Status      = StatusCodes.Status500InternalServerError,
                              ContentType = AppInfo.GitLfsContentType,
                              Value       = new GitLFSErrorResponse()
                              {
                                  Message = error
                              }.ToString()
                          };
                }

                bucketChecked = true;
            }

            var verifyUrl = QueryHelpers.AddQueryString(
                new Uri(configuration.GetBaseUrl(), $"api/v1/lfs/{project.Slug}/verify").ToString(),
                "token", GenerateUploadVerifyToken(obj));

            return(new LFSResponse.LFSObject(obj.Oid, obj.Size)
            {
                Actions = new Dictionary <string, LFSResponse.LFSObject.Action>()
                {
                    {
                        "upload", new LFSResponse.LFSObject.UploadAction()
                        {
                            Href = remoteStorage.CreatePresignedUploadURL(storagePath, S3UploadValidTime),
                            ExpiresIn = (int)UploadValidTime.TotalSeconds
                        }
                    },
                    {
                        "verify", new LFSResponse.LFSObject.UploadAction()
                        {
                            Href = verifyUrl,
                            ExpiresIn = (int)UploadValidTime.TotalSeconds
                        }
                    }
                }
            });
        }
示例#3
0
        private async ValueTask <LFSResponse.LFSObject> HandleDownload(LfsProject project, LFSRequest.LFSObject obj)
        {
            var existingObject = await database.LfsObjects
                                 .Where(o => o.LfsOid == obj.Oid && o.LfsProjectId == project.Id).Include(o => o.LfsProject)
                                 .FirstOrDefaultAsync();

            if (existingObject == null)
            {
                logger.LogWarning("Non-existing OID requested: {Oid}", obj.Oid);

                return(new LFSResponse.LFSObject(obj.Oid, obj.Size,
                                                 new LFSResponse.LFSObject.ErrorInfo(StatusCodes.Status404NotFound, "OID not found")));
            }

            var createdUrl = downloadUrls.CreateDownloadFor(existingObject, DownloadUrlExpireTime);

            return(new LFSResponse.LFSObject(obj.Oid, obj.Size)
            {
                Actions = new Dictionary <string, LFSResponse.LFSObject.Action>()
                {
                    {
                        "download", new LFSResponse.LFSObject.DownloadAction()
                        {
                            Href = createdUrl,
                            ExpiresIn = (int)DownloadExpireTime.TotalSeconds
                        }
                    }
                }
            });
        }