Skip to content

Commit 42ae965

Browse files
authored
Merge pull request #131 from LalitDeore/files
[feature] - files distribution system
2 parents 1baf72d + c8a4f2a commit 42ae965

File tree

3 files changed

+303
-46
lines changed

3 files changed

+303
-46
lines changed

db-connector.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10070,6 +10070,23 @@ func GetAllFiles(ctx context.Context, orgId, namespace string) ([]File, error) {
1007010070
}
1007110071
}
1007210072

10073+
// Should check if it's a child org and get parent orgs files if that is distributed to that child org
10074+
foundOrg, err := GetOrg(ctx, orgId)
10075+
if err == nil && len(foundOrg.ChildOrgs) == 0 && len(foundOrg.CreatorOrg) > 0 && foundOrg.CreatorOrg != orgId {
10076+
parentOrg, err := GetOrg(ctx, foundOrg.CreatorOrg)
10077+
if err == nil {
10078+
parentFiles, err := GetAllFiles(ctx, parentOrg.Id, namespace)
10079+
if err == nil {
10080+
for _, f := range parentFiles {
10081+
if !ArrayContains(f.SuborgDistribution, orgId) {
10082+
continue
10083+
}
10084+
files = append(files, f)
10085+
}
10086+
}
10087+
}
10088+
}
10089+
1007310090
if project.CacheDb {
1007410091
data, err := json.Marshal(files)
1007510092
if err != nil {

files.go

Lines changed: 244 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -571,17 +571,51 @@ func HandleGetFileNamespace(resp http.ResponseWriter, request *http.Request) {
571571
// FIXME: This double control is silly
572572
fileResponse.Files = append(fileResponse.Files, file)
573573
fileResponse.List = append(fileResponse.List, BaseFile{
574-
Name: file.Filename,
575-
ID: file.Id,
576-
Type: file.Type,
577-
UpdatedAt: file.UpdatedAt,
578-
Md5Sum: file.Md5sum,
579-
Status: file.Status,
580-
FileSize: file.FileSize,
574+
Name: file.Filename,
575+
ID: file.Id,
576+
Type: file.Type,
577+
UpdatedAt: file.UpdatedAt,
578+
Md5Sum: file.Md5sum,
579+
Status: file.Status,
580+
FileSize: file.FileSize,
581+
OrgId: file.OrgId,
582+
SuborgDistribution: file.SuborgDistribution,
581583
})
582584
}
583585
}
584586

587+
// If current org is sub org and file suborg distributed is true than add file to list
588+
foundOrg, err := GetOrg(ctx, user.ActiveOrg.Id)
589+
if err == nil && len(foundOrg.ChildOrgs) == 0 && len(foundOrg.CreatorOrg) > 0 {
590+
parentOrg, err := GetOrg(ctx, foundOrg.CreatorOrg)
591+
if err == nil {
592+
parentFiles, err := GetAllFiles(ctx, parentOrg.Id, namespace)
593+
if err == nil {
594+
for _, file := range parentFiles {
595+
596+
if !ArrayContains(file.SuborgDistribution, user.ActiveOrg.Id) {
597+
continue
598+
}
599+
600+
if file.Namespace == namespace {
601+
fileResponse.Files = append(fileResponse.Files, file)
602+
fileResponse.List = append(fileResponse.List, BaseFile{
603+
Name: file.Filename,
604+
ID: file.Id,
605+
Type: file.Type,
606+
UpdatedAt: file.UpdatedAt,
607+
Md5Sum: file.Md5sum,
608+
Status: file.Status,
609+
FileSize: file.FileSize,
610+
OrgId: file.OrgId,
611+
SuborgDistribution: file.SuborgDistribution,
612+
})
613+
}
614+
}
615+
}
616+
}
617+
}
618+
585619
//log.Printf("[DEBUG] Found %d (%d:%d) files in org %s (%s) for namespace '%s'", len(files), len(fileResponse.Files), len(fileResponse.List), user.ActiveOrg.Name, user.ActiveOrg.Id, namespace)
586620

587621
// Standards to load directly from Github if applicable
@@ -1971,3 +2005,206 @@ func HandleDownloadRemoteFiles(resp http.ResponseWriter, request *http.Request)
19712005
resp.WriteHeader(200)
19722006
resp.Write([]byte(fmt.Sprintf(`{"success": true}`)))
19732007
}
2008+
2009+
func HandleShareNamespace(resp http.ResponseWriter, request *http.Request) {
2010+
2011+
cors := HandleCors(resp, request)
2012+
if cors {
2013+
return
2014+
}
2015+
2016+
user, err := HandleApiAuthentication(resp, request)
2017+
if err != nil {
2018+
log.Printf("[AUDIT] Api authentication failed in share namespace: %s", err)
2019+
resp.WriteHeader(401)
2020+
resp.Write([]byte(`{"success": false}`))
2021+
return
2022+
}
2023+
2024+
if user.Role != "admin" {
2025+
log.Printf("User (%s) isn't admin during namespace share", user.Username)
2026+
resp.WriteHeader(401)
2027+
resp.Write([]byte(`{"success": false, "reason": "only admin can share namespace"}`))
2028+
return
2029+
}
2030+
2031+
var namespace string
2032+
location := strings.Split(request.URL.String(), "/")
2033+
if location[1] == "api" {
2034+
if len(location) <= 4 {
2035+
log.Printf("Path too short: %d", len(location))
2036+
resp.WriteHeader(401)
2037+
resp.Write([]byte(`{"success": false}`))
2038+
return
2039+
}
2040+
2041+
namespace = location[5]
2042+
}
2043+
2044+
body, err := ioutil.ReadAll(request.Body)
2045+
if err != nil {
2046+
log.Printf("Error with body read: %s", err)
2047+
resp.WriteHeader(401)
2048+
resp.Write([]byte(`{"success": false}`))
2049+
return
2050+
}
2051+
2052+
type shareNamespace struct {
2053+
SelectedFiles []string `json:"selectedFiles"`
2054+
}
2055+
2056+
var share shareNamespace
2057+
err = json.Unmarshal(body, &share)
2058+
if err != nil {
2059+
log.Printf("Failed unmarshaling (appauth): %s", err)
2060+
resp.WriteHeader(401)
2061+
resp.Write([]byte(`{"success": false}`))
2062+
return
2063+
}
2064+
2065+
if len(namespace) == 0 {
2066+
log.Printf("[ERROR] Missing namespace in share namespace")
2067+
resp.WriteHeader(401)
2068+
resp.Write([]byte(`{"success": false, "reason": "Missing namespace"}`))
2069+
return
2070+
}
2071+
2072+
if len(share.SelectedFiles) == 0 {
2073+
log.Printf("[ERROR] Missing selectedFiles in share namespace")
2074+
resp.WriteHeader(401)
2075+
resp.Write([]byte(`{"success": false, "reason": "Missing selectedFiles"}`))
2076+
return
2077+
}
2078+
2079+
ctx := GetContext(request)
2080+
for _, fileId := range share.SelectedFiles {
2081+
file, err := GetFile(ctx, fileId)
2082+
if err != nil {
2083+
log.Printf("[INFO] File %s not found: %s", fileId, err)
2084+
resp.WriteHeader(400)
2085+
resp.Write([]byte(`{"success": false}`))
2086+
return
2087+
}
2088+
2089+
file.Namespace = namespace
2090+
err = SetFile(ctx, *file)
2091+
if err != nil {
2092+
log.Printf("[ERROR] Failed setting file back to active")
2093+
resp.WriteHeader(500)
2094+
resp.Write([]byte(`{"success": false, "reason": "Failed setting file to active"}`))
2095+
return
2096+
}
2097+
}
2098+
2099+
log.Printf("[INFO] Successfully shared namespace %s for %d files", namespace, len(share.SelectedFiles))
2100+
resp.WriteHeader(200)
2101+
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "Namespace shared successfully!"}`)))
2102+
}
2103+
2104+
// destribute files to all sub orgs of parent org
2105+
func HandleSetFileConfig(resp http.ResponseWriter, request *http.Request) {
2106+
2107+
cors := HandleCors(resp, request)
2108+
if cors {
2109+
return
2110+
}
2111+
2112+
user, err := HandleApiAuthentication(resp, request)
2113+
if err != nil {
2114+
log.Printf("[AUDIT] Api authentication failed in load files: %s", err)
2115+
resp.WriteHeader(401)
2116+
resp.Write([]byte(`{"success": false}`))
2117+
return
2118+
}
2119+
2120+
if user.Role != "admin" {
2121+
log.Printf("User (%s) isn't admin during file edit config", user.Username)
2122+
resp.WriteHeader(401)
2123+
resp.Write([]byte(`{"success": false, "reason": "only admin can edit file config"}`))
2124+
return
2125+
}
2126+
2127+
var fileId string
2128+
location := strings.Split(request.URL.String(), "/")
2129+
if location[1] == "api" {
2130+
if len(location) <= 4 {
2131+
log.Printf("Path too short: %d", len(location))
2132+
resp.WriteHeader(401)
2133+
resp.Write([]byte(`{"success": false}`))
2134+
return
2135+
}
2136+
2137+
fileId = location[4]
2138+
}
2139+
2140+
body, err := ioutil.ReadAll(request.Body)
2141+
if err != nil {
2142+
log.Printf("Error with body read: %s", err)
2143+
resp.WriteHeader(401)
2144+
resp.Write([]byte(`{"success": false}`))
2145+
return
2146+
}
2147+
2148+
type configFile struct {
2149+
Id string `json:"id"`
2150+
Action string `json:"action"`
2151+
SelectedSuborg []string `json:"selected_suborgs"`
2152+
}
2153+
2154+
var config configFile
2155+
err = json.Unmarshal(body, &config)
2156+
if err != nil {
2157+
log.Printf("Failed unmarshaling (appauth): %s", err)
2158+
resp.WriteHeader(401)
2159+
resp.Write([]byte(`{"success": false}`))
2160+
return
2161+
}
2162+
2163+
if config.Id != fileId {
2164+
resp.WriteHeader(401)
2165+
resp.Write([]byte(`{"success": false, "reason": "Bad ID match"}`))
2166+
return
2167+
}
2168+
2169+
ctx := GetContext(request)
2170+
file, err := GetFile(ctx, fileId)
2171+
if err != nil {
2172+
log.Printf("[INFO] File %s not found: %s", fileId, err)
2173+
resp.WriteHeader(400)
2174+
resp.Write([]byte(`{"success": false}`))
2175+
return
2176+
}
2177+
2178+
if config.Action == "suborg_distribute" {
2179+
2180+
if len(config.SelectedSuborg) == 0 {
2181+
file.SuborgDistribution = []string{}
2182+
} else {
2183+
file.SuborgDistribution = config.SelectedSuborg
2184+
}
2185+
2186+
err = SetFile(ctx, *file)
2187+
if err != nil {
2188+
log.Printf("[ERROR] Failed setting file back to active")
2189+
resp.WriteHeader(500)
2190+
resp.Write([]byte(`{"success": false, "reason": "Failed setting file to active"}`))
2191+
return
2192+
}
2193+
2194+
}
2195+
2196+
//if current org is suborg and file is distributed, get the parent org file
2197+
foundOrg, err := GetOrg(ctx, user.ActiveOrg.Id)
2198+
if err == nil {
2199+
for _, childOrg := range foundOrg.ChildOrgs {
2200+
cacheKey := fmt.Sprintf("files_%s_%s", childOrg.Id, file.Namespace)
2201+
DeleteCache(ctx, cacheKey)
2202+
}
2203+
}
2204+
2205+
log.Printf("[INFO] Successfully updated file: %s for org: %s", file.Id, user.ActiveOrg.Id)
2206+
2207+
resp.WriteHeader(200)
2208+
resp.Write([]byte(fmt.Sprintf(`{"success": true, "reason": "File updated successfully!"}`)))
2209+
2210+
}

structs.go

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,38 +1434,39 @@ type NotificationCached struct {
14341434
}
14351435

14361436
type File struct {
1437-
Id string `json:"id" datastore:"id"`
1438-
ReferenceFileId string `json:"reference_file_id" datastore:"reference_file_id"`
1439-
Type string `json:"type" datastore:"type"`
1440-
CreatedAt int64 `json:"created_at" datastore:"created_at"`
1441-
UpdatedAt int64 `json:"updated_at" datastore:"updated_at"`
1442-
MetaAccessAt int64 `json:"meta_access_at" datastore:"meta_access_at"`
1443-
DownloadAt int64 `json:"last_downloaded" datastore:"last_downloaded"`
1444-
Description string `json:"description" datastore:"description"`
1445-
ExpiresAt string `json:"expires_at" datastore:"expires_at"`
1446-
Status string `json:"status" datastore:"status"`
1447-
Filename string `json:"filename" datastore:"filename"`
1448-
URL string `json:"url" datastore:"org"`
1449-
OrgId string `json:"org_id" datastore:"org_id"`
1450-
WorkflowId string `json:"workflow_id" datastore:"workflow_id"`
1451-
Workflows []string `json:"workflows" datastore:"workflows"`
1452-
DownloadPath string `json:"download_path" datastore:"download_path"`
1453-
Md5sum string `json:"md5_sum" datastore:"md5_sum"`
1454-
Sha256sum string `json:"sha256_sum" datastore:"sha256_sum"`
1455-
FileSize int64 `json:"filesize" datastore:"filesize"`
1456-
Duplicate bool `json:"duplicate" datastore:"duplicate"`
1457-
Subflows []string `json:"subflows" datastore:"subflows"`
1458-
Tags []string `json:"tags" datastore:"tags"`
1459-
StorageArea string `json:"storage_area" datastore:"storage_area"`
1460-
Etag int `json:"etag" datastore:"etag"`
1461-
ContentType string `json:"content_type" datastore:"content_type"`
1462-
UpdatedBy string `json:"updated_by" datastore:"updated_by"`
1463-
CreatedBy string `json:"created_by" datastore:"created_by"`
1464-
Namespace string `json:"namespace" datastore:"namespace"`
1465-
Encrypted bool `json:"encrypted" datastore:"encrypted"`
1466-
IsEdited bool `json:"isedited" datastore:"isedited"`
1467-
LastEditor string `json:"lasteditor" datastore:"lasteditor"`
1468-
OriginalMd5sum string `json:"Originalmd5_sum" datastore:"Originalmd5_sum"`
1437+
Id string `json:"id" datastore:"id"`
1438+
ReferenceFileId string `json:"reference_file_id" datastore:"reference_file_id"`
1439+
Type string `json:"type" datastore:"type"`
1440+
CreatedAt int64 `json:"created_at" datastore:"created_at"`
1441+
UpdatedAt int64 `json:"updated_at" datastore:"updated_at"`
1442+
MetaAccessAt int64 `json:"meta_access_at" datastore:"meta_access_at"`
1443+
DownloadAt int64 `json:"last_downloaded" datastore:"last_downloaded"`
1444+
Description string `json:"description" datastore:"description"`
1445+
ExpiresAt string `json:"expires_at" datastore:"expires_at"`
1446+
Status string `json:"status" datastore:"status"`
1447+
Filename string `json:"filename" datastore:"filename"`
1448+
URL string `json:"url" datastore:"org"`
1449+
OrgId string `json:"org_id" datastore:"org_id"`
1450+
WorkflowId string `json:"workflow_id" datastore:"workflow_id"`
1451+
Workflows []string `json:"workflows" datastore:"workflows"`
1452+
DownloadPath string `json:"download_path" datastore:"download_path"`
1453+
Md5sum string `json:"md5_sum" datastore:"md5_sum"`
1454+
Sha256sum string `json:"sha256_sum" datastore:"sha256_sum"`
1455+
FileSize int64 `json:"filesize" datastore:"filesize"`
1456+
Duplicate bool `json:"duplicate" datastore:"duplicate"`
1457+
Subflows []string `json:"subflows" datastore:"subflows"`
1458+
Tags []string `json:"tags" datastore:"tags"`
1459+
StorageArea string `json:"storage_area" datastore:"storage_area"`
1460+
Etag int `json:"etag" datastore:"etag"`
1461+
ContentType string `json:"content_type" datastore:"content_type"`
1462+
UpdatedBy string `json:"updated_by" datastore:"updated_by"`
1463+
CreatedBy string `json:"created_by" datastore:"created_by"`
1464+
Namespace string `json:"namespace" datastore:"namespace"`
1465+
Encrypted bool `json:"encrypted" datastore:"encrypted"`
1466+
IsEdited bool `json:"isedited" datastore:"isedited"`
1467+
LastEditor string `json:"lasteditor" datastore:"lasteditor"`
1468+
OriginalMd5sum string `json:"Originalmd5_sum" datastore:"Originalmd5_sum"`
1469+
SuborgDistribution []string `json:"suborg_distribution" datastore:"suborg_distribution"`
14691470
}
14701471

14711472
type DisabledRules struct {
@@ -2715,13 +2716,15 @@ type DataToSend struct {
27152716
}
27162717

27172718
type BaseFile struct {
2718-
Name string `json:"name"`
2719-
ID string `json:"id"`
2720-
Type string `json:"type"`
2721-
UpdatedAt int64 `json:"updated_at"`
2722-
Md5Sum string `json:"md5_sum"`
2723-
Status string `json:"status"`
2724-
FileSize int64 `json:"filesize"`
2719+
Name string `json:"name"`
2720+
ID string `json:"id"`
2721+
Type string `json:"type"`
2722+
UpdatedAt int64 `json:"updated_at"`
2723+
Md5Sum string `json:"md5_sum"`
2724+
Status string `json:"status"`
2725+
FileSize int64 `json:"filesize"`
2726+
OrgId string `json:"org_id"`
2727+
SuborgDistribution []string `json:"suborg_distribution"`
27252728
}
27262729

27272730
type FileResponse struct {

0 commit comments

Comments
 (0)