@@ -17,6 +17,7 @@ use crate::model::{
1717 contact:: { Contact , ContactOrderBy , ContactType } ,
1818 contribution:: { Contribution , ContributionType } ,
1919 contributor:: Contributor ,
20+ file:: { File , FileType } ,
2021 funding:: Funding ,
2122 imprint:: { Imprint , ImprintField , ImprintOrderBy } ,
2223 institution:: { CountryCode , Institution } ,
@@ -40,18 +41,39 @@ use crate::model::{
4041 Crud , Doi , Isbn , Orcid , Ror , Timestamp ,
4142} ;
4243use crate :: policy:: PolicyContext ;
44+ use crate :: storage:: { CloudFrontClient , S3Client } ;
4345use thoth_errors:: ThothError ;
4446
4547impl juniper:: Context for Context { }
4648
4749pub struct Context {
4850 pub db : Arc < PgPool > ,
4951 pub user : Option < IntrospectedUser > ,
52+ pub s3_client : Arc < S3Client > ,
53+ pub cloudfront_client : Arc < CloudFrontClient > ,
5054}
5155
5256impl Context {
53- pub fn new ( pool : Arc < PgPool > , user : Option < IntrospectedUser > ) -> Self {
54- Self { db : pool, user }
57+ pub fn new (
58+ pool : Arc < PgPool > ,
59+ user : Option < IntrospectedUser > ,
60+ s3_client : Arc < S3Client > ,
61+ cloudfront_client : Arc < CloudFrontClient > ,
62+ ) -> Self {
63+ Self {
64+ db : pool,
65+ user,
66+ s3_client,
67+ cloudfront_client,
68+ }
69+ }
70+
71+ pub fn s3_client ( & self ) -> & S3Client {
72+ self . s3_client . as_ref ( )
73+ }
74+
75+ pub fn cloudfront_client ( & self ) -> & CloudFrontClient {
76+ self . cloudfront_client . as_ref ( )
5577 }
5678}
5779
@@ -667,6 +689,10 @@ impl Work {
667689 )
668690 . map_err ( Into :: into)
669691 }
692+ #[ graphql( description = "Get the front cover file for this work" ) ]
693+ pub fn frontcover ( & self , context : & Context ) -> FieldResult < Option < File > > {
694+ File :: from_work_id ( & context. db , & self . work_id ) . map_err ( Into :: into)
695+ }
670696 #[ graphql( description = "Get references cited by this work" ) ]
671697 pub fn references (
672698 & self ,
@@ -907,12 +933,79 @@ impl Publication {
907933 . map_err ( Into :: into)
908934 }
909935
936+ #[ graphql( description = "Get the publication file for this publication" ) ]
937+ pub fn file ( & self , context : & Context ) -> FieldResult < Option < File > > {
938+ File :: from_publication_id ( & context. db , & self . publication_id ) . map_err ( Into :: into)
939+ }
940+
910941 #[ graphql( description = "Get the work to which this publication belongs" ) ]
911942 pub fn work ( & self , context : & Context ) -> FieldResult < Work > {
912943 Work :: from_id ( & context. db , & self . work_id ) . map_err ( Into :: into)
913944 }
914945}
915946
947+ #[ juniper:: graphql_object(
948+ Context = Context ,
949+ description = "A file stored in the system (publication file or front cover)."
950+ ) ]
951+ impl File {
952+ #[ graphql( description = "Thoth ID of the file" ) ]
953+ pub fn file_id ( & self ) -> & Uuid {
954+ & self . file_id
955+ }
956+
957+ #[ graphql( description = "Type of file (publication or frontcover)" ) ]
958+ pub fn file_type ( & self ) -> & FileType {
959+ & self . file_type
960+ }
961+
962+ #[ graphql( description = "Thoth ID of the work (for frontcovers)" ) ]
963+ pub fn work_id ( & self ) -> Option < & Uuid > {
964+ self . work_id . as_ref ( )
965+ }
966+
967+ #[ graphql( description = "Thoth ID of the publication (for publication files)" ) ]
968+ pub fn publication_id ( & self ) -> Option < & Uuid > {
969+ self . publication_id . as_ref ( )
970+ }
971+
972+ #[ graphql( description = "S3 object key (canonical DOI-based path)" ) ]
973+ pub fn object_key ( & self ) -> & String {
974+ & self . object_key
975+ }
976+
977+ #[ graphql( description = "Public CDN URL" ) ]
978+ pub fn cdn_url ( & self ) -> & String {
979+ & self . cdn_url
980+ }
981+
982+ #[ graphql( description = "MIME type used when serving the file" ) ]
983+ pub fn mime_type ( & self ) -> & String {
984+ & self . mime_type
985+ }
986+
987+ #[ graphql( description = "Size of the file in bytes" ) ]
988+ pub fn bytes ( & self ) -> i32 {
989+ // GraphQL does not support i64; files larger than 2GB will overflow.
990+ self . bytes as i32
991+ }
992+
993+ #[ graphql( description = "SHA-256 checksum of the stored file" ) ]
994+ pub fn sha256 ( & self ) -> & String {
995+ & self . sha256
996+ }
997+
998+ #[ graphql( description = "Date and time at which the file record was created" ) ]
999+ pub fn created_at ( & self ) -> Timestamp {
1000+ self . created_at
1001+ }
1002+
1003+ #[ graphql( description = "Date and time at which the file record was last updated" ) ]
1004+ pub fn updated_at ( & self ) -> Timestamp {
1005+ self . updated_at
1006+ }
1007+ }
1008+
9161009#[ juniper:: graphql_object( Context = Context , description = "An organisation that produces and distributes written texts." ) ]
9171010impl Publisher {
9181011 #[ graphql( description = "Thoth ID of the publisher" ) ]
0 commit comments