@@ -2,7 +2,9 @@ package coderd
2
2
3
3
import (
4
4
"context"
5
+ "crypto/sha256"
5
6
"database/sql"
7
+ "encoding/hex"
6
8
"encoding/json"
7
9
"errors"
8
10
"fmt"
@@ -23,6 +25,7 @@ import (
23
25
"github.com/coder/coder/coderd/provisionerdserver"
24
26
"github.com/coder/coder/coderd/rbac"
25
27
"github.com/coder/coder/codersdk"
28
+ "github.com/coder/coder/examples"
26
29
)
27
30
28
31
func (api * API ) templateVersion (rw http.ResponseWriter , r * http.Request ) {
@@ -834,19 +837,79 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
834
837
// Ensures the "owner" is properly applied.
835
838
tags := provisionerdserver .MutateTags (apiKey .UserID , req .ProvisionerTags )
836
839
837
- file , err := api .Database .GetFileByID (ctx , req .FileID )
838
- if errors .Is (err , sql .ErrNoRows ) {
839
- httpapi .Write (ctx , rw , http .StatusNotFound , codersdk.Response {
840
- Message : "File not found." ,
840
+ if req .ExampleID != "" && req .FileID != uuid .Nil {
841
+ httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
842
+ Message : "You cannot specify both an example_id and a file_id." ,
841
843
})
842
844
return
843
845
}
844
- if err != nil {
845
- httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
846
- Message : "Internal error fetching file." ,
847
- Detail : err .Error (),
846
+
847
+ var file database.File
848
+ var err error
849
+ // if example id is specified we need to copy the embedded tar into a new file in the database
850
+ if req .ExampleID != "" {
851
+ if ! api .Authorize (r , rbac .ActionCreate , rbac .ResourceFile .WithOwner (apiKey .UserID .String ())) {
852
+ httpapi .Forbidden (rw )
853
+ return
854
+ }
855
+ // ensure we can read the file that either already exists or will be created
856
+ if ! api .Authorize (r , rbac .ActionRead , rbac .ResourceFile .WithOwner (apiKey .UserID .String ())) {
857
+ httpapi .Forbidden (rw )
858
+ return
859
+ }
860
+
861
+ // lookup template tar from embedded examples
862
+ tar , err := examples .Archive (req .ExampleID )
863
+ if err != nil {
864
+ if xerrors .Is (err , examples .ErrNotFound ) {
865
+ httpapi .Write (ctx , rw , http .StatusBadRequest , codersdk.Response {
866
+ Message : "Example not found." ,
867
+ Detail : err .Error (),
868
+ })
869
+ return
870
+ }
871
+ httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
872
+ Message : "Internal error fetching example." ,
873
+ Detail : err .Error (),
874
+ })
875
+ return
876
+ }
877
+
878
+ // upload a copy of the template tar as a file in the database
879
+ hashBytes := sha256 .Sum256 (tar )
880
+ hash := hex .EncodeToString (hashBytes [:])
881
+ file , err = api .Database .InsertFile (ctx , database.InsertFileParams {
882
+ ID : uuid .New (),
883
+ Hash : hash ,
884
+ CreatedBy : apiKey .UserID ,
885
+ CreatedAt : database .Now (),
886
+ Mimetype : uploadFileContentTypeHeader ,
887
+ Data : tar ,
848
888
})
849
- return
889
+ if err != nil {
890
+ httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
891
+ Message : "Internal error creating file." ,
892
+ Detail : err .Error (),
893
+ })
894
+ return
895
+ }
896
+ }
897
+
898
+ if req .FileID != uuid .Nil {
899
+ file , err = api .Database .GetFileByID (ctx , req .FileID )
900
+ if errors .Is (err , sql .ErrNoRows ) {
901
+ httpapi .Write (ctx , rw , http .StatusNotFound , codersdk.Response {
902
+ Message : "File not found." ,
903
+ })
904
+ return
905
+ }
906
+ if err != nil {
907
+ httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
908
+ Message : "Internal error fetching file." ,
909
+ Detail : err .Error (),
910
+ })
911
+ return
912
+ }
850
913
}
851
914
852
915
if ! api .Authorize (r , rbac .ActionRead , file ) {
0 commit comments