added login page and authentication middleware, altought not yet implemented
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				ci/woodpecker/push/woodpecker Pipeline failed
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	ci/woodpecker/push/woodpecker Pipeline failed
				
			This commit is contained in:
		
							parent
							
								
									f6ab0bb4e2
								
							
						
					
					
						commit
						ddc95f49cd
					
				
					 39 changed files with 772 additions and 5911 deletions
				
			
		
							
								
								
									
										2
									
								
								.idea/dataSources.local.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								.idea/dataSources.local.xml
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
<project version="4">
 | 
					<project version="4">
 | 
				
			||||||
  <component name="dataSourceStorageLocal" created-in="IU-232.9559.62">
 | 
					  <component name="dataSourceStorageLocal" created-in="IU-232.9921.47">
 | 
				
			||||||
    <data-source name="filegate@filegate.dev.jmbit.de" uuid="28e7aa7f-2fe3-45ee-997f-c35496a4a3eb">
 | 
					    <data-source name="filegate@filegate.dev.jmbit.de" uuid="28e7aa7f-2fe3-45ee-997f-c35496a4a3eb">
 | 
				
			||||||
      <database-info product="PostgreSQL" version="15.3 (Debian 15.3-0+deb12u1)" jdbc-version="4.2" driver-name="PostgreSQL JDBC Driver" driver-version="42.6.0" dbms="POSTGRES" exact-version="15.3" exact-driver-version="42.6">
 | 
					      <database-info product="PostgreSQL" version="15.3 (Debian 15.3-0+deb12u1)" jdbc-version="4.2" driver-name="PostgreSQL JDBC Driver" driver-version="42.6.0" dbms="POSTGRES" exact-version="15.3" exact-driver-version="42.6">
 | 
				
			||||||
        <identifier-quote-string>"</identifier-quote-string>
 | 
					        <identifier-quote-string>"</identifier-quote-string>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										5182
									
								
								.idea/dataSources/28e7aa7f-2fe3-45ee-997f-c35496a4a3eb.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										5182
									
								
								.idea/dataSources/28e7aa7f-2fe3-45ee-997f-c35496a4a3eb.xml
									
										
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										7
									
								
								.idea/sqldialects.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										7
									
								
								.idea/sqldialects.xml
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -1,7 +0,0 @@
 | 
				
			||||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
					 | 
				
			||||||
<project version="4">
 | 
					 | 
				
			||||||
  <component name="SqlDialectMappings">
 | 
					 | 
				
			||||||
    <file url="file://$PROJECT_DIR$/pgsetup.sql" dialect="PostgreSQL" />
 | 
					 | 
				
			||||||
    <file url="file://$PROJECT_DIR$/sqliteschema.sql" dialect="SQLite" />
 | 
					 | 
				
			||||||
  </component>
 | 
					 | 
				
			||||||
</project>
 | 
					 | 
				
			||||||
							
								
								
									
										133
									
								
								.idea/workspace.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										133
									
								
								.idea/workspace.xml
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -8,7 +8,45 @@
 | 
				
			||||||
    <option name="autoReloadType" value="ALL" />
 | 
					    <option name="autoReloadType" value="ALL" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
  <component name="ChangeListManager">
 | 
					  <component name="ChangeListManager">
 | 
				
			||||||
    <list default="true" id="eeedfed2-369e-4948-a46c-18edddaeec9c" name="Changes" comment="" />
 | 
					    <list default="true" id="eeedfed2-369e-4948-a46c-18edddaeec9c" name="Changes" comment="">
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/Makefile" afterDir="false" />
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/database/user.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/filegate.service" afterDir="false" />
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/templates/login.gohtml" afterDir="false" />
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/web/auth/hashPassword.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/web/auth/login.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/web/auth/middleware.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/web/routes.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change afterPath="$PROJECT_DIR$/web/session.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/.idea/dataSources.local.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources.local.xml" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/.idea/dataSources/28e7aa7f-2fe3-45ee-997f-c35496a4a3eb.xml" beforeDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/.idea/sqldialects.xml" beforeDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/Dockerfile" beforeDir="false" afterPath="$PROJECT_DIR$/Dockerfile" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/Installation.md" beforeDir="false" afterPath="$PROJECT_DIR$/Installation.md" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/config.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/config.yaml" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/config/config.go" beforeDir="false" afterPath="$PROJECT_DIR$/config/config.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/config/defaults.go" beforeDir="false" afterPath="$PROJECT_DIR$/config/defaults.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/config/struct.go" beforeDir="false" afterPath="$PROJECT_DIR$/config/struct.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/database/files.go" beforeDir="false" afterPath="$PROJECT_DIR$/database/files.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/database/models.go" beforeDir="false" afterPath="$PROJECT_DIR$/database/models.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/database/postgresql.go" beforeDir="false" afterPath="$PROJECT_DIR$/database/postgresql.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/files/filemanager.go" beforeDir="false" afterPath="$PROJECT_DIR$/files/filemanager.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/files/minio.go" beforeDir="false" afterPath="$PROJECT_DIR$/files/minio.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/files/staticanalysis.go" beforeDir="false" afterPath="$PROJECT_DIR$/files/staticanalysis.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/go.mod" beforeDir="false" afterPath="$PROJECT_DIR$/go.mod" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/go.sum" beforeDir="false" afterPath="$PROJECT_DIR$/go.sum" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/main.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/pgsetup.sql" beforeDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/podthing/downloadContainer.go" beforeDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/podthing/podmanager.go" beforeDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/sqliteschema.sql" beforeDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/templates/filelist.gohtml" beforeDir="false" afterPath="$PROJECT_DIR$/templates/filelist.gohtml" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/templates/footer.gohtml" beforeDir="false" afterPath="$PROJECT_DIR$/templates/footer.gohtml" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/web/browser.go" beforeDir="false" afterPath="$PROJECT_DIR$/web/browser/browser.go" afterDir="false" />
 | 
				
			||||||
 | 
					      <change beforePath="$PROJECT_DIR$/web/filelist.go" beforeDir="false" afterPath="$PROJECT_DIR$/web/filelist.go" afterDir="false" />
 | 
				
			||||||
 | 
					    </list>
 | 
				
			||||||
    <option name="SHOW_DIALOG" value="false" />
 | 
					    <option name="SHOW_DIALOG" value="false" />
 | 
				
			||||||
    <option name="HIGHLIGHT_CONFLICTS" value="true" />
 | 
					    <option name="HIGHLIGHT_CONFLICTS" value="true" />
 | 
				
			||||||
    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
 | 
					    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
 | 
				
			||||||
| 
						 | 
					@ -39,48 +77,48 @@
 | 
				
			||||||
    <option name="hideEmptyMiddlePackages" value="true" />
 | 
					    <option name="hideEmptyMiddlePackages" value="true" />
 | 
				
			||||||
    <option name="showLibraryContents" value="true" />
 | 
					    <option name="showLibraryContents" value="true" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
  <component name="PropertiesComponent">{
 | 
					  <component name="PropertiesComponent"><![CDATA[{
 | 
				
			||||||
  "keyToString": {
 | 
					  "keyToString": {
 | 
				
			||||||
    "DefaultGoTemplateProperty": "Go File",
 | 
					    "DefaultGoTemplateProperty": "Go File",
 | 
				
			||||||
    "DefaultHtmlFileTemplate": "HTML File",
 | 
					    "DefaultHtmlFileTemplate": "HTML File",
 | 
				
			||||||
    "RunOnceActivity.OpenProjectViewOnStart": "true",
 | 
					    "RunOnceActivity.OpenProjectViewOnStart": "true",
 | 
				
			||||||
    "RunOnceActivity.ShowReadmeOnStart": "true",
 | 
					    "RunOnceActivity.ShowReadmeOnStart": "true",
 | 
				
			||||||
    "RunOnceActivity.go.formatter.settings.were.checked": "true",
 | 
					    "RunOnceActivity.go.formatter.settings.were.checked": "true",
 | 
				
			||||||
    "RunOnceActivity.go.migrated.go.modules.settings": "true",
 | 
					    "RunOnceActivity.go.migrated.go.modules.settings": "true",
 | 
				
			||||||
    "RunOnceActivity.go.modules.automatic.dependencies.download": "true",
 | 
					    "RunOnceActivity.go.modules.automatic.dependencies.download": "true",
 | 
				
			||||||
    "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
 | 
					    "RunOnceActivity.go.modules.go.list.on.any.changes.was.set": "true",
 | 
				
			||||||
    "SHARE_PROJECT_CONFIGURATION_FILES": "true",
 | 
					    "SHARE_PROJECT_CONFIGURATION_FILES": "true",
 | 
				
			||||||
    "WebServerToolWindowFactoryState": "false",
 | 
					    "WebServerToolWindowFactoryState": "false",
 | 
				
			||||||
    "git-widget-placeholder": "main",
 | 
					    "git-widget-placeholder": "main",
 | 
				
			||||||
    "go.import.settings.migrated": "true",
 | 
					    "go.import.settings.migrated": "true",
 | 
				
			||||||
    "go.sdk.automatically.set": "true",
 | 
					    "go.sdk.automatically.set": "true",
 | 
				
			||||||
    "last_opened_file_path": "/root",
 | 
					    "last_opened_file_path": "/home/johannes/git/filegate/filegate/templates",
 | 
				
			||||||
    "list.type.of.created.stylesheet": "CSS",
 | 
					    "list.type.of.created.stylesheet": "CSS",
 | 
				
			||||||
    "node.js.detected.package.eslint": "true",
 | 
					    "node.js.detected.package.eslint": "true",
 | 
				
			||||||
    "node.js.detected.package.tslint": "true",
 | 
					    "node.js.detected.package.tslint": "true",
 | 
				
			||||||
    "node.js.selected.package.eslint": "(autodetect)",
 | 
					    "node.js.selected.package.eslint": "(autodetect)",
 | 
				
			||||||
    "node.js.selected.package.tslint": "(autodetect)",
 | 
					    "node.js.selected.package.tslint": "(autodetect)",
 | 
				
			||||||
    "nodejs_package_manager_path": "npm",
 | 
					    "nodejs_package_manager_path": "npm",
 | 
				
			||||||
    "ruby.rails.projectView.checked": "true",
 | 
					    "ruby.rails.projectView.checked": "true",
 | 
				
			||||||
    "run.code.analysis.last.selected.profile": "pProject Default",
 | 
					    "run.code.analysis.last.selected.profile": "pProject Default",
 | 
				
			||||||
    "settings.editor.selected.configurable": "database.query.execution",
 | 
					    "settings.editor.selected.configurable": "preferences.lookFeel",
 | 
				
			||||||
    "vue.rearranger.settings.migration": "true"
 | 
					    "vue.rearranger.settings.migration": "true"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "keyToStringList": {
 | 
					  "keyToStringList": {
 | 
				
			||||||
    "DatabaseDriversLRU": [
 | 
					    "DatabaseDriversLRU": [
 | 
				
			||||||
      "sqlite"
 | 
					      "sqlite"
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "RunConfigurationTargetLRU": [
 | 
					    "RunConfigurationTargetLRU": [
 | 
				
			||||||
      "28e7aa7f-2fe3-45ee-997f-c35496a4a3eb/database/\"filegate\""
 | 
					      "28e7aa7f-2fe3-45ee-997f-c35496a4a3eb/database/\"filegate\""
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "com.intellij.ide.scratch.LRUPopupBuilder$1/": [
 | 
					    "com.intellij.ide.scratch.LRUPopupBuilder$1/": [
 | 
				
			||||||
      "SQLite"
 | 
					      "SQLite"
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "com.intellij.ide.scratch.LRUPopupBuilder$1/SQL Dialect": [
 | 
					    "com.intellij.ide.scratch.LRUPopupBuilder$1/SQL Dialect": [
 | 
				
			||||||
      "SQLite"
 | 
					      "SQLite"
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}</component>
 | 
					}]]></component>
 | 
				
			||||||
  <component name="RdControllerToolWindowsLayoutState" isNewUi="true">
 | 
					  <component name="RdControllerToolWindowsLayoutState" isNewUi="true">
 | 
				
			||||||
    <layout>
 | 
					    <layout>
 | 
				
			||||||
      <window_info id="Space Code Reviews" />
 | 
					      <window_info id="Space Code Reviews" />
 | 
				
			||||||
| 
						 | 
					@ -118,10 +156,11 @@
 | 
				
			||||||
      <recent name="$PROJECT_DIR$/files" />
 | 
					      <recent name="$PROJECT_DIR$/files" />
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <key name="CopyFile.RECENT_KEYS">
 | 
					    <key name="CopyFile.RECENT_KEYS">
 | 
				
			||||||
      <recent name="$PROJECT_DIR$" />
 | 
					 | 
				
			||||||
      <recent name="$PROJECT_DIR$/templates" />
 | 
					      <recent name="$PROJECT_DIR$/templates" />
 | 
				
			||||||
 | 
					      <recent name="$PROJECT_DIR$" />
 | 
				
			||||||
    </key>
 | 
					    </key>
 | 
				
			||||||
    <key name="MoveFile.RECENT_KEYS">
 | 
					    <key name="MoveFile.RECENT_KEYS">
 | 
				
			||||||
 | 
					      <recent name="$PROJECT_DIR$/web/browser" />
 | 
				
			||||||
      <recent name="$PROJECT_DIR$/" />
 | 
					      <recent name="$PROJECT_DIR$/" />
 | 
				
			||||||
      <recent name="$PROJECT_DIR$/src/" />
 | 
					      <recent name="$PROJECT_DIR$/src/" />
 | 
				
			||||||
      <recent name="$PROJECT_DIR$/database" />
 | 
					      <recent name="$PROJECT_DIR$/database" />
 | 
				
			||||||
| 
						 | 
					@ -204,11 +243,11 @@
 | 
				
			||||||
    </configuration>
 | 
					    </configuration>
 | 
				
			||||||
    <recent_temporary>
 | 
					    <recent_temporary>
 | 
				
			||||||
      <list>
 | 
					      <list>
 | 
				
			||||||
        <item itemvalue="Database Script.pgsetup.sql" />
 | 
					 | 
				
			||||||
        <item itemvalue="Go Build.go run ." />
 | 
					 | 
				
			||||||
        <item itemvalue="Docker.devel-compose.yml: Compose Deployment" />
 | 
					        <item itemvalue="Docker.devel-compose.yml: Compose Deployment" />
 | 
				
			||||||
        <item itemvalue="Docker.Dockerfile" />
 | 
					        <item itemvalue="Docker.Dockerfile" />
 | 
				
			||||||
        <item itemvalue="Docker.Dockerfile builder" />
 | 
					        <item itemvalue="Docker.Dockerfile builder" />
 | 
				
			||||||
 | 
					        <item itemvalue="Go Build.go run ." />
 | 
				
			||||||
 | 
					        <item itemvalue="Database Script.pgsetup.sql" />
 | 
				
			||||||
      </list>
 | 
					      </list>
 | 
				
			||||||
    </recent_temporary>
 | 
					    </recent_temporary>
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
| 
						 | 
					@ -246,12 +285,26 @@
 | 
				
			||||||
      <workItem from="1692525884012" duration="3960000" />
 | 
					      <workItem from="1692525884012" duration="3960000" />
 | 
				
			||||||
      <workItem from="1692549204776" duration="6122000" />
 | 
					      <workItem from="1692549204776" duration="6122000" />
 | 
				
			||||||
      <workItem from="1694330563801" duration="7776000" />
 | 
					      <workItem from="1694330563801" duration="7776000" />
 | 
				
			||||||
 | 
					      <workItem from="1695542369457" duration="4674000" />
 | 
				
			||||||
 | 
					      <workItem from="1695990751089" duration="514000" />
 | 
				
			||||||
 | 
					      <workItem from="1695991319785" duration="59000" />
 | 
				
			||||||
 | 
					      <workItem from="1695991389809" duration="448000" />
 | 
				
			||||||
 | 
					      <workItem from="1695991846569" duration="902000" />
 | 
				
			||||||
 | 
					      <workItem from="1696234645954" duration="4224000" />
 | 
				
			||||||
 | 
					      <workItem from="1696248724514" duration="4736000" />
 | 
				
			||||||
 | 
					      <workItem from="1696311727002" duration="6423000" />
 | 
				
			||||||
    </task>
 | 
					    </task>
 | 
				
			||||||
    <servers />
 | 
					    <servers />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
  <component name="TypeScriptGeneratedFilesManager">
 | 
					  <component name="TypeScriptGeneratedFilesManager">
 | 
				
			||||||
    <option name="version" value="3" />
 | 
					    <option name="version" value="3" />
 | 
				
			||||||
  </component>
 | 
					  </component>
 | 
				
			||||||
 | 
					  <component name="UnknownFeatures">
 | 
				
			||||||
 | 
					    <option featureType="dependencySupport" implementationName="executable:docker" />
 | 
				
			||||||
 | 
					    <option featureType="dependencySupport" implementationName="executable:podman" />
 | 
				
			||||||
 | 
					    <option featureType="dependencySupport" implementationName="executable:kubectl" />
 | 
				
			||||||
 | 
					    <option featureType="dependencySupport" implementationName="executable:terraform" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
  <component name="Vcs.Log.Tabs.Properties">
 | 
					  <component name="Vcs.Log.Tabs.Properties">
 | 
				
			||||||
    <option name="TAB_STATES">
 | 
					    <option name="TAB_STATES">
 | 
				
			||||||
      <map>
 | 
					      <map>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ LABEL authors="Johannes Bülow <johannes.buelow@jmbit.de>"
 | 
				
			||||||
# Get all the stuff for CGO and Podman bindings
 | 
					# Get all the stuff for CGO and Podman bindings
 | 
				
			||||||
WORKDIR /usr/local/src
 | 
					WORKDIR /usr/local/src
 | 
				
			||||||
COPY ./ ./
 | 
					COPY ./ ./
 | 
				
			||||||
RUN go get . && go mod download && go build -o filegate
 | 
					RUN go get . && go mod download && go build -v -x -race -o filegate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FROM alpine
 | 
					FROM alpine
 | 
				
			||||||
LABEL authors="Johannes Bülow <johannes.buelow@jmbit.de>"
 | 
					LABEL authors="Johannes Bülow <johannes.buelow@jmbit.de>"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,22 +1,27 @@
 | 
				
			||||||
# Installation
 | 
					# Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Prerequisites
 | 
					## Prerequisites
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OS: Linux, preferrably Debian
 | 
					OS: Linux, preferrably Debian
 | 
				
			||||||
Database: PostgreSQL
 | 
					Database: PostgreSQL
 | 
				
			||||||
Object Storage: Preferrably MinIO, but anny S3-Compatible Storage should do
 | 
					Object Storage: Preferrably MinIO, but anny S3-Compatible Storage should do
 | 
				
			||||||
Container Engine: Podman
 | 
					Container Engine: Podman
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Installation
 | 
					## Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 1. Install the OS
 | 
					### 1. Install the OS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
This depends a lot on the Distribution you are using, but should usually be documented there
 | 
					This depends a lot on the Distribution you are using, but should usually be documented there
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 2. Install required Packages
 | 
					### 2. Install required Packages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
For Debian, this would be:
 | 
					For Debian, this would be:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```shell
 | 
					```shell
 | 
				
			||||||
export DEBIAN_FRONTEND="noninteractive"
 | 
					export DEBIAN_FRONTEND="noninteractive"
 | 
				
			||||||
apt-get update
 | 
					apt-get update
 | 
				
			||||||
apt-get upgrade -y
 | 
					apt-get upgrade -y
 | 
				
			||||||
apt-get install podman file -y
 | 
					apt-get install podman file postgres-y
 | 
				
			||||||
# Please check the official install instructions for your up to date minio Version
 | 
					# Please check the official install instructions for your up to date minio Version
 | 
				
			||||||
wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20230816201730.0.0_amd64.deb -O minio.deb
 | 
					wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio_20230816201730.0.0_amd64.deb -O minio.deb
 | 
				
			||||||
dpkg -i minio.deb
 | 
					dpkg -i minio.deb
 | 
				
			||||||
| 
						 | 
					@ -24,10 +29,19 @@ curl https://dl.min.io/client/mc/release/linux-amd64/mc -o /usr/local/bin/mc
 | 
				
			||||||
chmod +x /usr/local/bin/mc
 | 
					chmod +x /usr/local/bin/mc
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Enable the podman socket for your user:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					systemctl --user enable --now podman.socket
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### 3. Configure Minio
 | 
					### 3. Configure Minio
 | 
				
			||||||
More advanced Information can be found in the [Minio Documentation](https://min.io/docs/minio/linux/operations/installation.html)
 | 
					
 | 
				
			||||||
 | 
					More advanced Information can be found in
 | 
				
			||||||
 | 
					the [Minio Documentation](https://min.io/docs/minio/linux/operations/installation.html)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example `/etc/default/minio`:
 | 
					Example `/etc/default/minio`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```shell
 | 
					```shell
 | 
				
			||||||
# MINIO_ROOT_USER and MINIO_ROOT_PASSWORD sets the root account for the MinIO server.
 | 
					# MINIO_ROOT_USER and MINIO_ROOT_PASSWORD sets the root account for the MinIO server.
 | 
				
			||||||
# This user has unrestricted permissions to perform S3 and administrative API operations on any resource in the deployment.
 | 
					# This user has unrestricted permissions to perform S3 and administrative API operations on any resource in the deployment.
 | 
				
			||||||
| 
						 | 
					@ -46,24 +60,34 @@ MINIO_VOLUMES="/var/lib/minio"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Uncomment the following line and replace the value with the correct hostname for the local machine and port for the MinIO server (9000 by default).
 | 
					# Uncomment the following line and replace the value with the correct hostname for the local machine and port for the MinIO server (9000 by default).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#MINIO_SERVER_URL="http://minio.example.net:9000"
 | 
					MINIO_SERVER_URL="http://localhost:9000"
 | 
				
			||||||
MINIO_CONSOLE_PORT=9001
 | 
					MINIO_CONSOLE_PORT=9001
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 3.1. Create User
 | 
					#### 3.1. Create User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### 3.2. Create Bucket
 | 
					#### 3.2. Create Bucket
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
### 4. Configure PostgreSQL
 | 
					### 4. Configure PostgreSQL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Example script to set up PostgreSQL for Filegate:
 | 
					Example script to set up PostgreSQL for Filegate:
 | 
				
			||||||
 | 
					*Slightly Jank (could have better permission management)*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```sql
 | 
					```sql
 | 
				
			||||||
CREATE DATABASE filegate;
 | 
					CREATE
 | 
				
			||||||
CREATE user fgowner WITH PASSWORD 'supersecretpassword';
 | 
					DATABASE filegate;
 | 
				
			||||||
CREATE user fgwriter WITH PASSWORD 'alsoverysecretpassword';
 | 
					CREATE
 | 
				
			||||||
CREATE USER fgreader WITH PASSWORD 'anothersecretpassword';
 | 
					user filegate WITH PASSWORD 'supersecretpassword';
 | 
				
			||||||
GRANT ALL PRIVILEGES ON DATABASE filegate TO fgowner WITH GRANT OPTION ;
 | 
					-- CREATE user fgwriter WITH PASSWORD 'alsoverysecretpassword';
 | 
				
			||||||
GRANT ALL PRIVILEGES ON SCHEMA public TO fgowner WITH GRANT OPTION;
 | 
					--CREATE USER fgreader WITH PASSWORD 'anothersecretpassword';
 | 
				
			||||||
 | 
					GRANT ALL PRIVILEGES ON DATABASE
 | 
				
			||||||
 | 
					filegate TO filegate WITH GRANT OPTION;
 | 
				
			||||||
 | 
					GRANT ALL PRIVILEGES ON SCHEMA
 | 
				
			||||||
 | 
					public TO filegate WITH GRANT OPTION;
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
If you have changed the usernames for this database, you will also need to change them in `pgsetup.sql`
 | 
					### 5. Install filegate itself
 | 
				
			||||||
 | 
					```shell
 | 
				
			||||||
 | 
					make
 | 
				
			||||||
 | 
					sudo make install
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
							
								
								
									
										19
									
								
								Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								Makefile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					build: dependencies
 | 
				
			||||||
 | 
						GOOS=linux go build -v -x -race -o filegate .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dependencies:
 | 
				
			||||||
 | 
						go get .
 | 
				
			||||||
 | 
						go mod download
 | 
				
			||||||
 | 
					run: dependencies
 | 
				
			||||||
 | 
						go run .
 | 
				
			||||||
 | 
					install: build
 | 
				
			||||||
 | 
						mkdir -P /etc/filegate
 | 
				
			||||||
 | 
						mkdir -P /var/local/filegate/
 | 
				
			||||||
 | 
						cp filegate /usr/local/bin/filegate
 | 
				
			||||||
 | 
						cp filegate.service /etc/systemd/system/filegate.service
 | 
				
			||||||
 | 
						useradd -d /var/local/filegate -m -U filegate
 | 
				
			||||||
 | 
						chownr -R filegate:filegate /var/local/filegate
 | 
				
			||||||
 | 
						systemctl daemon-reload
 | 
				
			||||||
 | 
						systemctl enable --now filegate
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						rm filegate
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,11 @@ manual analysis
 | 
				
			||||||
# Icon
 | 
					# Icon
 | 
				
			||||||
Based on https://pictogrammers.com/library/mdi/icon/gate/ and https://pictogrammers.com/library/mdi/icon/floppy/
 | 
					Based on https://pictogrammers.com/library/mdi/icon/gate/ and https://pictogrammers.com/library/mdi/icon/floppy/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# AccessLevel
 | 
				
			||||||
 | 
					0 = User // can add files, view status of files created by them, edit comments, download cleared files
 | 
				
			||||||
 | 
					3 = Helpdesk // can see all files, full analysis of all files, can manually trigger steps
 | 
				
			||||||
 | 
					5 = Analyst // can do everything with files, but not change the software settings
 | 
				
			||||||
 | 
					10 = Admin // Can do literally anything
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Useful Links for Development
 | 
					## Useful Links for Development
 | 
				
			||||||
https://chenyitian.gitbooks.io/gin-tutorials/content/gin/8.html // Go Templates
 | 
					https://chenyitian.gitbooks.io/gin-tutorials/content/gin/8.html // Go Templates
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										34
									
								
								config.yaml
									
										
									
									
									
								
							
							
						
						
									
										34
									
								
								config.yaml
									
										
									
									
									
								
							| 
						 | 
					@ -1,20 +1,20 @@
 | 
				
			||||||
serverhostname: filegate.dev.jmbit.de
 | 
					serverhostname: 0.0.0.0
 | 
				
			||||||
serverport: 80
 | 
					serverport: 8080
 | 
				
			||||||
loglevel: info
 | 
					loglevel: info
 | 
				
			||||||
 | 
					scratchdisk: "/var/tmp/filegate"
 | 
				
			||||||
 | 
					trustedproxies:
 | 
				
			||||||
 | 
					  - 127.0.0.1
 | 
				
			||||||
db:
 | 
					db:
 | 
				
			||||||
    hostname: filegate.dev.jmbit.de
 | 
					  hostname: localhost
 | 
				
			||||||
    port: 5432
 | 
					  port: 5432
 | 
				
			||||||
    owner: fgowner
 | 
					  name: filegate
 | 
				
			||||||
    ownerpassword: 0b26aca2-b10f-496e-9bd8-8bbfb143ad8b
 | 
					  user: filegate
 | 
				
			||||||
    writer: fgwriter
 | 
					  password: 80f9859c-d2fe-4864-a962-a58adbdcb5f3
 | 
				
			||||||
    writerpassword: d5af6fde-7156-4ffa-ab0e-951df657990d
 | 
					 | 
				
			||||||
    reader: fgreader
 | 
					 | 
				
			||||||
    readerpassword: a788a837-f984-4b20-97db-b6dfd6b97a56
 | 
					 | 
				
			||||||
minio:
 | 
					minio:
 | 
				
			||||||
    accesskeyid: lZvkgrfXNbEMye6BSf6s
 | 
					  accesskeyid: lZvkgrfXNbEMye6BSf6s
 | 
				
			||||||
    accesskeysecret: U109MtkE1jcc6qm3SIGk3IEZsq1cl8vTxqIRr3ZH
 | 
					  accesskeysecret: U109MtkE1jcc6qm3SIGk3IEZsq1cl8vTxqIRr3ZH
 | 
				
			||||||
    hostname: filegate.dev.jmbit.de
 | 
					  hostname: 127.0.0.1
 | 
				
			||||||
    port: 9000
 | 
					  port: 9000
 | 
				
			||||||
    bucket: filegate
 | 
					  bucket: filegate
 | 
				
			||||||
    usessl: false
 | 
					  usessl: false
 | 
				
			||||||
    location: filegate-local
 | 
					  location: filegate-local
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,26 +8,36 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var Cfg Config
 | 
					var Cfg Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ParseConfig() {
 | 
					func init() {
 | 
				
			||||||
	cfg := getDefaults()
 | 
						ParseConfig()
 | 
				
			||||||
	file, err := os.Open("config.yaml")
 | 
						if os.Getenv("GIN_MODE") != "release" {
 | 
				
			||||||
	if os.Getenv("GIN_MODE") == "release" {
 | 
							log.Print(Cfg)
 | 
				
			||||||
		file, err = os.Open("/etc/filegate/config.yaml")
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err != nil && err.Error() == "open config.yaml: no such file or directory" {
 | 
					}
 | 
				
			||||||
		createDefaultConfig()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer func(file *os.File) {
 | 
					 | 
				
			||||||
		err := file.Close()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		}
 | 
					func ParseConfig() {
 | 
				
			||||||
	}(file)
 | 
						log.Println("Reading Config")
 | 
				
			||||||
 | 
						cfg := getDefaults()
 | 
				
			||||||
 | 
						configFile, err := os.ReadFile(findConfigFile())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = yaml.Unmarshal(configFile, &cfg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = os.Mkdir(cfg.ScratchDisk, 600) // Directory to temporarily store files on host system
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Cfg = cfg
 | 
						Cfg = cfg
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func createDefaultConfig() {
 | 
					func createDefaultConfig() {
 | 
				
			||||||
 | 
						log.Println("Creating default config file")
 | 
				
			||||||
	file, err := os.Create("config.yaml")
 | 
						file, err := os.Create("config.yaml")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatalf("Could not create default config file: %v", err)
 | 
							log.Fatalf("Could not create default config file: %v", err)
 | 
				
			||||||
| 
						 | 
					@ -44,3 +54,24 @@ func createDefaultConfig() {
 | 
				
			||||||
		log.Fatalf("failed to encode default Config YAML: %v", err)
 | 
							log.Fatalf("failed to encode default Config YAML: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Checks first for a config file in the current directory, then in /etc/filegate/
 | 
				
			||||||
 | 
					func findConfigFile() string {
 | 
				
			||||||
 | 
						log.Println("Finding Config file")
 | 
				
			||||||
 | 
						if file, err := os.Stat("config.yaml"); err == nil {
 | 
				
			||||||
 | 
							log.Println(file)
 | 
				
			||||||
 | 
							return "config.yaml"
 | 
				
			||||||
 | 
						} else if file, err = os.Stat("config.yml"); err == nil {
 | 
				
			||||||
 | 
							log.Println(file)
 | 
				
			||||||
 | 
							return "config.yml"
 | 
				
			||||||
 | 
						} else if file, err = os.Stat("/etc/filegate/config.yaml"); err == nil {
 | 
				
			||||||
 | 
							log.Println(file)
 | 
				
			||||||
 | 
							return "/etc/filegate/config.yaml"
 | 
				
			||||||
 | 
						} else if file, err = os.Stat("/etc/filegate/config.yml"); err == nil {
 | 
				
			||||||
 | 
							log.Println(file)
 | 
				
			||||||
 | 
							return "/etc/filegate/config.yml"
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							createDefaultConfig()
 | 
				
			||||||
 | 
							return "config.yaml"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,9 @@ func getDefaults() Config {
 | 
				
			||||||
		ServerHostname: "localhost",
 | 
							ServerHostname: "localhost",
 | 
				
			||||||
		ServerPort:     8080,
 | 
							ServerPort:     8080,
 | 
				
			||||||
		LogLevel:       "info",
 | 
							LogLevel:       "info",
 | 
				
			||||||
 | 
							ScratchDisk:    "/var/tmp/filegate",
 | 
				
			||||||
 | 
							SessionSecret:  uuid.NewString(),
 | 
				
			||||||
 | 
							TrustedProxies: []string{"127.0.0.1"},
 | 
				
			||||||
		DB: struct {
 | 
							DB: struct {
 | 
				
			||||||
			Hostname string
 | 
								Hostname string
 | 
				
			||||||
			Port     int
 | 
								Port     int
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,9 @@ type Config struct {
 | 
				
			||||||
	ServerHostname string
 | 
						ServerHostname string
 | 
				
			||||||
	ServerPort     int
 | 
						ServerPort     int
 | 
				
			||||||
	LogLevel       string
 | 
						LogLevel       string
 | 
				
			||||||
 | 
						ScratchDisk    string
 | 
				
			||||||
 | 
						SessionSecret  string
 | 
				
			||||||
 | 
						TrustedProxies []string
 | 
				
			||||||
	DB             struct {
 | 
						DB             struct {
 | 
				
			||||||
		Hostname string
 | 
							Hostname string
 | 
				
			||||||
		Port     int
 | 
							Port     int
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,11 @@
 | 
				
			||||||
package database
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func CreateFile(name string, url string, comment string, blob string) (uint, error) {
 | 
					func CreateFile(name string, url string, comment string, blob string) (uint, error) {
 | 
				
			||||||
	file := File{
 | 
						file := File{
 | 
				
			||||||
		Name:    name,
 | 
							Name:    name,
 | 
				
			||||||
| 
						 | 
					@ -31,6 +37,7 @@ func SetSimpleAttributes(id uint, mime string, size int64, sha256 string, sha1 s
 | 
				
			||||||
	file.Properties.Md5 = md5
 | 
						file.Properties.Md5 = md5
 | 
				
			||||||
	file.Properties.FileCmd = fileCmd
 | 
						file.Properties.FileCmd = fileCmd
 | 
				
			||||||
	file.Properties.Extension = extension
 | 
						file.Properties.Extension = extension
 | 
				
			||||||
 | 
						DB.Save(&file)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func CountFilesEntries() int64 {
 | 
					func CountFilesEntries() int64 {
 | 
				
			||||||
| 
						 | 
					@ -58,11 +65,31 @@ func GetFileBlob(id uint) string {
 | 
				
			||||||
	return file.Blob
 | 
						return file.Blob
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func GetFileList(page int, count int) []File {
 | 
					func GetFileList(page int, count int, c *gin.Context) ([]File, error) {
 | 
				
			||||||
	// TODO Implement paged queries to DB
 | 
						query, err := searchQueryBuilder(c)
 | 
				
			||||||
	_ = page
 | 
						if err != nil {
 | 
				
			||||||
	_ = count
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	var list []File
 | 
						var list []File
 | 
				
			||||||
	DB.Find(&list)
 | 
						DB.Limit(page * count).Where(query).Find(&list)
 | 
				
			||||||
	return list
 | 
					
 | 
				
			||||||
 | 
						return list, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func searchQueryBuilder(c *gin.Context) (*File, error) {
 | 
				
			||||||
 | 
						// TODO Add parsing for all File properties
 | 
				
			||||||
 | 
						var query File
 | 
				
			||||||
 | 
						if c.Query("id") != "" {
 | 
				
			||||||
 | 
							id, err := strconv.ParseUint(c.Query("id"), 10, 0)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Printf("Could not Convert ID from filter to int: %v", err)
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							query.ID = uint(id)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if c.Query("name") != "" {
 | 
				
			||||||
 | 
							query.Name = c.Query("name")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &query, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,27 @@ type User struct {
 | 
				
			||||||
	Name        string `gorm:"unique"`
 | 
						Name        string `gorm:"unique"`
 | 
				
			||||||
	DisplayName string
 | 
						DisplayName string
 | 
				
			||||||
	Email       string
 | 
						Email       string
 | 
				
			||||||
	Oauth2Sub   string
 | 
						PassHash    string
 | 
				
			||||||
	Role        string
 | 
						//	Oauth2Sub   string
 | 
				
			||||||
 | 
						Role UserRole
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UserRole struct {
 | 
				
			||||||
 | 
						gorm.Model
 | 
				
			||||||
 | 
						ID          uint
 | 
				
			||||||
 | 
						Name        string
 | 
				
			||||||
 | 
						AccessLevel int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Pod struct {
 | 
				
			||||||
 | 
						gorm.Model
 | 
				
			||||||
 | 
						ID         string
 | 
				
			||||||
 | 
						Name       string
 | 
				
			||||||
 | 
						Type       PodType
 | 
				
			||||||
 | 
						BoundPorts []int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PodType struct {
 | 
				
			||||||
 | 
						ID   uint
 | 
				
			||||||
 | 
						Name string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ package database
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"git.jmbit.de/filegate/filegate/config"
 | 
						"git.jmbit.de/filegate/filegate/config"
 | 
				
			||||||
 | 
						gormsessions "github.com/gin-contrib/sessions/gorm"
 | 
				
			||||||
	"gorm.io/driver/postgres"
 | 
						"gorm.io/driver/postgres"
 | 
				
			||||||
	"gorm.io/gorm"
 | 
						"gorm.io/gorm"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
| 
						 | 
					@ -10,13 +11,15 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var dbconf = config.Cfg.DB
 | 
					var dbconf = config.Cfg.DB
 | 
				
			||||||
var DB *gorm.DB
 | 
					var DB *gorm.DB
 | 
				
			||||||
 | 
					var SessionStore gormsessions.Store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Connect() {
 | 
					func Connect() {
 | 
				
			||||||
	dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable",
 | 
						dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=disable",
 | 
				
			||||||
		dbconf.Hostname, dbconf.User, dbconf.Password, dbconf.Name)
 | 
							dbconf.Hostname, dbconf.User, dbconf.Password, dbconf.Name, dbconf.Port)
 | 
				
			||||||
	db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
 | 
						db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatalf("Can't connect to DB: %v", err)
 | 
							log.Fatalf("Can't connect to DB: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	DB = db
 | 
						DB = db
 | 
				
			||||||
 | 
						SessionStore = gormsessions.NewStore(db, true, []byte(config.Cfg.SessionSecret))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										57
									
								
								database/user.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								database/user.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,57 @@
 | 
				
			||||||
 | 
					package database
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func CreateUser(name string, displayName string, email string, passHash string, role UserRole) error {
 | 
				
			||||||
 | 
						user := User{
 | 
				
			||||||
 | 
							Name:        name,
 | 
				
			||||||
 | 
							DisplayName: displayName,
 | 
				
			||||||
 | 
							Email:       email,
 | 
				
			||||||
 | 
							PassHash:    passHash,
 | 
				
			||||||
 | 
							Role:        role,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := DB.Create(&user).Error; err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DeleteUser(name string) error {
 | 
				
			||||||
 | 
						var user User
 | 
				
			||||||
 | 
						DB.First(&user, name)
 | 
				
			||||||
 | 
						if user.Name == "" {
 | 
				
			||||||
 | 
							return errors.New("user not found")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						DB.Delete(&user)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func UpdatePassword(name string, passHash string) error {
 | 
				
			||||||
 | 
						var user User
 | 
				
			||||||
 | 
						DB.First(&user, name)
 | 
				
			||||||
 | 
						if user.Name == "" {
 | 
				
			||||||
 | 
							return errors.New("user not found")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						user.PassHash = passHash
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func UpdateEmail(name string, email string) error {
 | 
				
			||||||
 | 
						var user User
 | 
				
			||||||
 | 
						DB.First(&user, name)
 | 
				
			||||||
 | 
						if user.Name == "" {
 | 
				
			||||||
 | 
							return errors.New("user not found")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						user.Email = email
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetUser(name string) (User, error) {
 | 
				
			||||||
 | 
						var user User
 | 
				
			||||||
 | 
						DB.First(&user, name)
 | 
				
			||||||
 | 
						if user.Name == "" {
 | 
				
			||||||
 | 
							return user, errors.New("user not found")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return user, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										17
									
								
								filegate.service
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								filegate.service
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					[Unit]
 | 
				
			||||||
 | 
					Description=Enterprise Download Management Portal
 | 
				
			||||||
 | 
					After=postgresql.service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Service]
 | 
				
			||||||
 | 
					Type=simple
 | 
				
			||||||
 | 
					User=filegate
 | 
				
			||||||
 | 
					Restart=always
 | 
				
			||||||
 | 
					RestartSec=3
 | 
				
			||||||
 | 
					PrivateTmp=yes
 | 
				
			||||||
 | 
					ExecStart=/usr/local/bin/filegate
 | 
				
			||||||
 | 
					ProtectSystem=strict
 | 
				
			||||||
 | 
					InaccessiblePaths=/root /home
 | 
				
			||||||
 | 
					NoNewPrivileges=yes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[Install]
 | 
				
			||||||
 | 
					WantedBy=multi-user.target
 | 
				
			||||||
| 
						 | 
					@ -2,29 +2,12 @@ package files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"git.jmbit.de/filegate/filegate/database"
 | 
						"git.jmbit.de/filegate/filegate/database"
 | 
				
			||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
	"github.com/minio/minio-go/v7"
 | 
						"github.com/minio/minio-go/v7"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func StorageDirectory() {
 | 
					 | 
				
			||||||
	if _, err := os.Stat("./filesstore"); os.IsNotExist(err) {
 | 
					 | 
				
			||||||
		err := os.Mkdir("./filestore", 770)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			log.Println(fmt.Sprintf("Could not create File directory: %s", err))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if os.Getenv("GIN_MODE") != "release" {
 | 
					 | 
				
			||||||
		err := os.RemoveAll("./filestore/*")
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func UploadFile(id uint, blob string, c *gin.Context) error {
 | 
					func UploadFile(id uint, blob string, c *gin.Context) error {
 | 
				
			||||||
	ctx := context.Background()
 | 
						ctx := context.Background()
 | 
				
			||||||
	file, err := c.FormFile("file")
 | 
						file, err := c.FormFile("file")
 | 
				
			||||||
| 
						 | 
					@ -42,3 +25,11 @@ func UploadFile(id uint, blob string, c *gin.Context) error {
 | 
				
			||||||
	go RunStaticAnalysis(id)
 | 
						go RunStaticAnalysis(id)
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetFile returns a pointer to a File stored in Minio by passing it the UUID ("Blob"-ID) of the file
 | 
				
			||||||
 | 
					func GetFile(uuid string) (*minio.Object, error) {
 | 
				
			||||||
 | 
						ctx := context.Background()
 | 
				
			||||||
 | 
						object, err := MinioClient.GetObject(ctx, minioConfig.Bucket, uuid, minio.GetObjectOptions{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return object, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ var MinioClient = minioConnect()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func minioConnect() *minio.Client {
 | 
					func minioConnect() *minio.Client {
 | 
				
			||||||
	endpoint := fmt.Sprintf("%s:%d", minioConfig.Hostname, minioConfig.Port)
 | 
						endpoint := fmt.Sprintf("%s:%d", minioConfig.Hostname, minioConfig.Port)
 | 
				
			||||||
 | 
						log.Printf("Minio Endpoint: %s", endpoint)
 | 
				
			||||||
	accessKeyID := minioConfig.AccessKeyID
 | 
						accessKeyID := minioConfig.AccessKeyID
 | 
				
			||||||
	accessKeySecret := minioConfig.AccessKeySecret
 | 
						accessKeySecret := minioConfig.AccessKeySecret
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import (
 | 
				
			||||||
	"crypto/sha1"
 | 
						"crypto/sha1"
 | 
				
			||||||
	"crypto/sha256"
 | 
						"crypto/sha256"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"git.jmbit.de/filegate/filegate/config"
 | 
				
			||||||
	"git.jmbit.de/filegate/filegate/database"
 | 
						"git.jmbit.de/filegate/filegate/database"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
| 
						 | 
					@ -70,9 +71,40 @@ func fileSize(path string) int64 {
 | 
				
			||||||
	return filesize
 | 
						return filesize
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func RunStaticAnalysis(id uint) {
 | 
					//TODO: Use container instead of running on local disk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	filepath := fmt.Sprintf("./filestore/%s", id)
 | 
					// RunStaticAnalysis populates the File Properties Table for a given file
 | 
				
			||||||
 | 
					func RunStaticAnalysis(id uint) {
 | 
				
			||||||
 | 
						file := database.GetFileByID(id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						filepath := fmt.Sprintf("%s/%d/%s", config.Cfg.ScratchDisk, file.ID, file.Properties.OriginalName)
 | 
				
			||||||
 | 
						err := os.Mkdir(fmt.Sprintf("%s/%d", config.Cfg.ScratchDisk, file.ID), 700)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							log.Printf("Error Creating analysis directory, %v", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fileObject, err := GetFile(file.Blob)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("Error getting file from S3, %v", err)
 | 
				
			||||||
 | 
							fileObject.Close()
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						localFile, err := os.Create(filepath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("Error Creating analysis file, %v", err)
 | 
				
			||||||
 | 
							fileObject.Close()
 | 
				
			||||||
 | 
							localFile.Close()
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if _, err = io.Copy(localFile, fileObject); err != nil {
 | 
				
			||||||
 | 
							log.Printf("Could not Copy S3 File to local disk: %v", err)
 | 
				
			||||||
 | 
							fileObject.Close()
 | 
				
			||||||
 | 
							localFile.Close()
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fileObject.Close()
 | 
				
			||||||
 | 
						localFile.Close()
 | 
				
			||||||
	mimeType := mimeType(filepath)
 | 
						mimeType := mimeType(filepath)
 | 
				
			||||||
	fileCmd := fileCmd(filepath)
 | 
						fileCmd := fileCmd(filepath)
 | 
				
			||||||
	fileExtension := fileExtension(filepath)
 | 
						fileExtension := fileExtension(filepath)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										8
									
								
								go.mod
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
										
									
									
									
								
							| 
						 | 
					@ -4,10 +4,11 @@ go 1.20
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/containers/podman/v4 v4.6.0
 | 
						github.com/containers/podman/v4 v4.6.0
 | 
				
			||||||
 | 
						github.com/gin-contrib/sessions v0.0.5
 | 
				
			||||||
	github.com/gin-gonic/gin v1.9.1
 | 
						github.com/gin-gonic/gin v1.9.1
 | 
				
			||||||
	github.com/google/uuid v1.3.0
 | 
						github.com/google/uuid v1.3.0
 | 
				
			||||||
	github.com/mattn/go-sqlite3 v1.14.17
 | 
					 | 
				
			||||||
	github.com/minio/minio-go/v7 v7.0.62
 | 
						github.com/minio/minio-go/v7 v7.0.62
 | 
				
			||||||
 | 
						golang.org/x/crypto v0.12.0
 | 
				
			||||||
	gopkg.in/yaml.v3 v3.0.1
 | 
						gopkg.in/yaml.v3 v3.0.1
 | 
				
			||||||
	gorm.io/driver/postgres v1.5.2
 | 
						gorm.io/driver/postgres v1.5.2
 | 
				
			||||||
	gorm.io/gorm v1.25.4
 | 
						gorm.io/gorm v1.25.4
 | 
				
			||||||
| 
						 | 
					@ -71,8 +72,11 @@ require (
 | 
				
			||||||
	github.com/golang/protobuf v1.5.3 // indirect
 | 
						github.com/golang/protobuf v1.5.3 // indirect
 | 
				
			||||||
	github.com/google/go-containerregistry v0.15.2 // indirect
 | 
						github.com/google/go-containerregistry v0.15.2 // indirect
 | 
				
			||||||
	github.com/google/go-intervals v0.0.2 // indirect
 | 
						github.com/google/go-intervals v0.0.2 // indirect
 | 
				
			||||||
 | 
						github.com/gorilla/context v1.1.1 // indirect
 | 
				
			||||||
	github.com/gorilla/mux v1.8.0 // indirect
 | 
						github.com/gorilla/mux v1.8.0 // indirect
 | 
				
			||||||
	github.com/gorilla/schema v1.2.0 // indirect
 | 
						github.com/gorilla/schema v1.2.0 // indirect
 | 
				
			||||||
 | 
						github.com/gorilla/securecookie v1.1.1 // indirect
 | 
				
			||||||
 | 
						github.com/gorilla/sessions v1.2.1 // indirect
 | 
				
			||||||
	github.com/hashicorp/errwrap v1.1.0 // indirect
 | 
						github.com/hashicorp/errwrap v1.1.0 // indirect
 | 
				
			||||||
	github.com/hashicorp/go-multierror v1.1.1 // indirect
 | 
						github.com/hashicorp/go-multierror v1.1.1 // indirect
 | 
				
			||||||
	github.com/jackc/pgpassfile v1.0.0 // indirect
 | 
						github.com/jackc/pgpassfile v1.0.0 // indirect
 | 
				
			||||||
| 
						 | 
					@ -134,12 +138,12 @@ require (
 | 
				
			||||||
	github.com/ulikunitz/xz v0.5.11 // indirect
 | 
						github.com/ulikunitz/xz v0.5.11 // indirect
 | 
				
			||||||
	github.com/vbatts/tar-split v0.11.3 // indirect
 | 
						github.com/vbatts/tar-split v0.11.3 // indirect
 | 
				
			||||||
	github.com/vbauerster/mpb/v8 v8.4.0 // indirect
 | 
						github.com/vbauerster/mpb/v8 v8.4.0 // indirect
 | 
				
			||||||
 | 
						github.com/wader/gormstore/v2 v2.0.0 // indirect
 | 
				
			||||||
	go.etcd.io/bbolt v1.3.7 // indirect
 | 
						go.etcd.io/bbolt v1.3.7 // indirect
 | 
				
			||||||
	go.mongodb.org/mongo-driver v1.11.3 // indirect
 | 
						go.mongodb.org/mongo-driver v1.11.3 // indirect
 | 
				
			||||||
	go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
 | 
						go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
 | 
				
			||||||
	go.opencensus.io v0.24.0 // indirect
 | 
						go.opencensus.io v0.24.0 // indirect
 | 
				
			||||||
	golang.org/x/arch v0.3.0 // indirect
 | 
						golang.org/x/arch v0.3.0 // indirect
 | 
				
			||||||
	golang.org/x/crypto v0.12.0 // indirect
 | 
					 | 
				
			||||||
	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
 | 
						golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
 | 
				
			||||||
	golang.org/x/mod v0.10.0 // indirect
 | 
						golang.org/x/mod v0.10.0 // indirect
 | 
				
			||||||
	golang.org/x/net v0.14.0 // indirect
 | 
						golang.org/x/net v0.14.0 // indirect
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										23
									
								
								main.go
									
										
									
									
									
								
							
							
						
						
									
										23
									
								
								main.go
									
										
									
									
									
								
							| 
						 | 
					@ -1,3 +1,5 @@
 | 
				
			||||||
 | 
					//go:build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
| 
						 | 
					@ -5,13 +7,13 @@ import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"git.jmbit.de/filegate/filegate/config"
 | 
						"git.jmbit.de/filegate/filegate/config"
 | 
				
			||||||
	"git.jmbit.de/filegate/filegate/database"
 | 
						"git.jmbit.de/filegate/filegate/database"
 | 
				
			||||||
	"git.jmbit.de/filegate/filegate/files"
 | 
						"git.jmbit.de/filegate/filegate/pods"
 | 
				
			||||||
	"git.jmbit.de/filegate/filegate/web"
 | 
						"git.jmbit.de/filegate/filegate/web"
 | 
				
			||||||
 | 
						"github.com/gin-contrib/sessions"
 | 
				
			||||||
	"github.com/gin-gonic/gin"
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
	"html/template"
 | 
						"html/template"
 | 
				
			||||||
	"log"
 | 
						"log"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:embed assets/jquery.min.js assets/custom.css assets/bootstrap/css/*.min.css assets/bootstrap/js/bootstrap.min.js assets/favicon.ico assets/logo.svg
 | 
					//go:embed assets/jquery.min.js assets/custom.css assets/bootstrap/css/*.min.css assets/bootstrap/js/bootstrap.min.js assets/favicon.ico assets/logo.svg
 | 
				
			||||||
| 
						 | 
					@ -21,29 +23,19 @@ var assetsFS embed.FS
 | 
				
			||||||
var templatesFS embed.FS
 | 
					var templatesFS embed.FS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	if runtime.GOOS == "windows" {
 | 
					 | 
				
			||||||
		fmt.Println("This Software is not supported on Windows")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	config.ParseConfig()
 | 
					 | 
				
			||||||
	addr := fmt.Sprintf("%s:%d", config.Cfg.ServerHostname, config.Cfg.ServerPort)
 | 
						addr := fmt.Sprintf("%s:%d", config.Cfg.ServerHostname, config.Cfg.ServerPort)
 | 
				
			||||||
	database.Connect()
 | 
						database.Connect()
 | 
				
			||||||
	// podthing.TestPodman()
 | 
						pods.TestPodman()
 | 
				
			||||||
	files.StorageDirectory()
 | 
					 | 
				
			||||||
	router := gin.Default()
 | 
						router := gin.Default()
 | 
				
			||||||
	templates := template.Must(template.New("").ParseFS(templatesFS, "templates/*.gohtml"))
 | 
						templates := template.Must(template.New("").ParseFS(templatesFS, "templates/*.gohtml"))
 | 
				
			||||||
	router.ForwardedByClientIP = true
 | 
						router.ForwardedByClientIP = true
 | 
				
			||||||
	err := router.SetTrustedProxies([]string{"127.0.0.1"})
 | 
						router.Use(sessions.Sessions("mySession", database.SessionStore))
 | 
				
			||||||
 | 
						err := router.SetTrustedProxies(config.Cfg.TrustedProxies)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Println(err)
 | 
							log.Println(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	router.SetHTMLTemplate(templates)
 | 
						router.SetHTMLTemplate(templates)
 | 
				
			||||||
	router.StaticFS("/static", http.FS(assetsFS))
 | 
						router.StaticFS("/static", http.FS(assetsFS))
 | 
				
			||||||
	router.GET("/", web.GetIndex)
 | 
					 | 
				
			||||||
	router.GET("/file/:id", web.GetFileView)
 | 
					 | 
				
			||||||
	router.GET("/file/", web.GetFileList)
 | 
					 | 
				
			||||||
	router.POST("/file/new", web.PostSubmitFileUrl)
 | 
					 | 
				
			||||||
	router.POST("/file/upload", web.PostUploadFile)
 | 
					 | 
				
			||||||
	router.GET("/browser/:id/")
 | 
					 | 
				
			||||||
	router.GET("favicon.ico", func(c *gin.Context) {
 | 
						router.GET("favicon.ico", func(c *gin.Context) {
 | 
				
			||||||
		file, _ := assetsFS.ReadFile("assets/favicon.ico")
 | 
							file, _ := assetsFS.ReadFile("assets/favicon.ico")
 | 
				
			||||||
		c.Data(
 | 
							c.Data(
 | 
				
			||||||
| 
						 | 
					@ -52,6 +44,7 @@ func main() {
 | 
				
			||||||
			file,
 | 
								file,
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
						router = web.SetRoutes(router)
 | 
				
			||||||
	err = router.Run(addr)
 | 
						err = router.Run(addr)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatal(err)
 | 
							log.Fatal(err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										62
									
								
								pgsetup.sql
									
										
									
									
									
								
							
							
						
						
									
										62
									
								
								pgsetup.sql
									
										
									
									
									
								
							| 
						 | 
					@ -1,62 +0,0 @@
 | 
				
			||||||
DROP TABLE IF EXISTS status CASCADE ;
 | 
					 | 
				
			||||||
DROP TABLE IF EXISTS file CASCADE ;
 | 
					 | 
				
			||||||
DROP TABLE IF EXISTS file_properties CASCADE ;
 | 
					 | 
				
			||||||
DROP TABLE IF EXISTS dynamic_analysis CASCADE ;
 | 
					 | 
				
			||||||
DROP TABLE IF EXISTS file_attachment CASCADE ;
 | 
					 | 
				
			||||||
-- DROP all tables (Only for development purposes
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS status
 | 
					 | 
				
			||||||
(
 | 
					 | 
				
			||||||
    id      INTEGER PRIMARY KEY,
 | 
					 | 
				
			||||||
    name    VARCHAR(64),
 | 
					 | 
				
			||||||
    comment VARCHAR(2048)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS file_properties
 | 
					 | 
				
			||||||
(
 | 
					 | 
				
			||||||
    id            SERIAL PRIMARY KEY,
 | 
					 | 
				
			||||||
    sha256        VARCHAR(64),
 | 
					 | 
				
			||||||
    sha1          VARCHAR(40),
 | 
					 | 
				
			||||||
    md5           VARCHAR(32),
 | 
					 | 
				
			||||||
    extension     VARCHAR(80),
 | 
					 | 
				
			||||||
    file_cmd      VARCHAR(512),
 | 
					 | 
				
			||||||
    original_name VARCHAR(256),
 | 
					 | 
				
			||||||
    url           VARCHAR(2048),
 | 
					 | 
				
			||||||
    size          BIGINT
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS file
 | 
					 | 
				
			||||||
(
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    id         VARCHAR(36) PRIMARY KEY,
 | 
					 | 
				
			||||||
    name       VARCHAR(64),
 | 
					 | 
				
			||||||
    mime       VARCHAR(256),
 | 
					 | 
				
			||||||
    comment    VARCHAR(2048),
 | 
					 | 
				
			||||||
    status     INT,
 | 
					 | 
				
			||||||
    created    BIGINT,
 | 
					 | 
				
			||||||
    properties INT,
 | 
					 | 
				
			||||||
    FOREIGN KEY (status)
 | 
					 | 
				
			||||||
        REFERENCES status (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (properties)
 | 
					 | 
				
			||||||
        REFERENCES file_properties (id)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS file_attachment
 | 
					 | 
				
			||||||
(
 | 
					 | 
				
			||||||
    id SERIAL PRIMARY KEY,
 | 
					 | 
				
			||||||
    type VARCHAR(32),
 | 
					 | 
				
			||||||
    comment VARCHAR(2048),
 | 
					 | 
				
			||||||
    file_id VARCHAR(36),
 | 
					 | 
				
			||||||
    FOREIGN KEY (file_id)
 | 
					 | 
				
			||||||
        REFERENCES file (id)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
GRANT INSERT, UPDATE, DELETE ON file, file_attachment, file_properties, status TO fgwriter;
 | 
					 | 
				
			||||||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO fgreader;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
INSERT INTO status (id, name, comment)
 | 
					 | 
				
			||||||
VALUES (0, 'New', 'Freshly uploaded file');
 | 
					 | 
				
			||||||
INSERT INTO status (id, name, comment)
 | 
					 | 
				
			||||||
VALUES (1, 'Processing', 'File is now being analyzed');
 | 
					 | 
				
			||||||
INSERT INTO status (id, name, comment)
 | 
					 | 
				
			||||||
VALUES (2, 'Denied', 'File download was denied');
 | 
					 | 
				
			||||||
INSERT INTO status (id, name, comment)
 | 
					 | 
				
			||||||
VALUES (3, 'Granted', 'File download was granted');
 | 
					 | 
				
			||||||
							
								
								
									
										47
									
								
								pods/autoAnalysis.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								pods/autoAnalysis.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,47 @@
 | 
				
			||||||
 | 
					package pods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"git.jmbit.de/filegate/filegate/database"
 | 
				
			||||||
 | 
						"git.jmbit.de/filegate/filegate/files"
 | 
				
			||||||
 | 
						"github.com/containers/podman/v4/pkg/bindings/containers"
 | 
				
			||||||
 | 
						"github.com/containers/podman/v4/pkg/bindings/images"
 | 
				
			||||||
 | 
						"github.com/containers/podman/v4/pkg/specgen"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AnalysisContainer struct {
 | 
				
			||||||
 | 
						UUID          string
 | 
				
			||||||
 | 
						containerFile string
 | 
				
			||||||
 | 
						fileID        uint
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CreateAutoAnalysisContainer creates a Static analysis Container with the file
 | 
				
			||||||
 | 
					// returns the UUID of the container and the path of the file
 | 
				
			||||||
 | 
					func CreateAutoAnalysisContainer(fileID uint) AnalysisContainer {
 | 
				
			||||||
 | 
						image := "git.jmbit.de/filegate/utility-containers:staticanalysis"
 | 
				
			||||||
 | 
						conn := socketConnection()
 | 
				
			||||||
 | 
						_, err := images.Pull(conn, image, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						s := specgen.NewSpecGenerator(image, false)
 | 
				
			||||||
 | 
						createResponse, err := containers.CreateWithSpec(conn, s, nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Println(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := containers.Start(conn, createResponse.ID, nil); err != nil {
 | 
				
			||||||
 | 
							log.Println(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						file := database.GetFileByID(fileID)
 | 
				
			||||||
 | 
						fileObject, err := files.GetFile(file.Blob)
 | 
				
			||||||
 | 
						_, err = containers.CopyFromArchive(conn, createResponse.ID, fmt.Sprintf("/mnt/%s", file.Properties.OriginalName), fileObject)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return AnalysisContainer{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return AnalysisContainer{
 | 
				
			||||||
 | 
							UUID:          createResponse.ID,
 | 
				
			||||||
 | 
							containerFile: fmt.Sprintf("/mnt/%s", file.Properties.OriginalName),
 | 
				
			||||||
 | 
							fileID:        file.ID,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package podthing
 | 
					package pods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"github.com/containers/podman/v4/pkg/bindings/containers"
 | 
						"github.com/containers/podman/v4/pkg/bindings/containers"
 | 
				
			||||||
							
								
								
									
										24
									
								
								pods/podmanager.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								pods/podmanager.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,24 @@
 | 
				
			||||||
 | 
					package pods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"github.com/containers/podman/v4/pkg/bindings"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Socket = socketConnection()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func socketConnection() context.Context {
 | 
				
			||||||
 | 
						uri := fmt.Sprintf("unix:///run/user/%d/podman/podman.sock", os.Getuid())
 | 
				
			||||||
 | 
						conn, err := bindings.NewConnection(context.Background(), uri)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return conn
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestPodman() {
 | 
				
			||||||
 | 
						_ = socketConnection()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,45 +0,0 @@
 | 
				
			||||||
package podthing
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"context"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"github.com/containers/podman/v4/pkg/bindings"
 | 
					 | 
				
			||||||
	"github.com/containers/podman/v4/pkg/bindings/containers"
 | 
					 | 
				
			||||||
	"github.com/containers/podman/v4/pkg/bindings/images"
 | 
					 | 
				
			||||||
	"github.com/containers/podman/v4/pkg/specgen"
 | 
					 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func socketConnection() context.Context {
 | 
					 | 
				
			||||||
	uri := fmt.Sprintf("unix:///run/user/%d/podman/podman.sock", os.Getuid())
 | 
					 | 
				
			||||||
	conn, err := bindings.NewConnection(context.Background(), uri)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Println(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return conn
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestPodman() {
 | 
					 | 
				
			||||||
	conn := socketConnection()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err := images.Pull(conn, "quay.io/libpod/alpine_nginx", nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	s := specgen.NewSpecGenerator("quay.io/libpod/alpine_nginx", false)
 | 
					 | 
				
			||||||
	s.Name = "fg-test"
 | 
					 | 
				
			||||||
	createResponse, err := containers.CreateWithSpec(conn, s, nil)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := containers.Start(conn, createResponse.ID, nil); err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := containers.Kill(conn, createResponse.ID, nil); err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err, _ := containers.Remove(conn, createResponse.ID, nil); err != nil {
 | 
					 | 
				
			||||||
		log.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,35 +0,0 @@
 | 
				
			||||||
DROP TABLE IF EXISTS status;
 | 
					 | 
				
			||||||
DROP TABLE IF EXISTS files;
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS status (
 | 
					 | 
				
			||||||
                                      id INTEGER PRIMARY KEY ,
 | 
					 | 
				
			||||||
                                      name TEXT,
 | 
					 | 
				
			||||||
                                      comment TEXT);
 | 
					 | 
				
			||||||
CREATE TABLE IF NOT EXISTS files (
 | 
					 | 
				
			||||||
                                     id TEXT PRIMARY KEY,
 | 
					 | 
				
			||||||
                                     name TEXT,
 | 
					 | 
				
			||||||
                                     url TEXT NOT NULL,
 | 
					 | 
				
			||||||
                                     -- blob TEXT,
 | 
					 | 
				
			||||||
                                     mime TEXT,
 | 
					 | 
				
			||||||
                                     original_name TEXT,
 | 
					 | 
				
			||||||
                                     comment TEXT,
 | 
					 | 
				
			||||||
                                     size INTEGER,
 | 
					 | 
				
			||||||
                                     sha256 TEXT,
 | 
					 | 
				
			||||||
                                     sha1 TEXT,
 | 
					 | 
				
			||||||
                                     md5 TEXT,
 | 
					 | 
				
			||||||
                                     status_id INTEGER,
 | 
					 | 
				
			||||||
                                     file_cmd TEXT,
 | 
					 | 
				
			||||||
                                     created INTEGER,
 | 
					 | 
				
			||||||
                                     extension TEXT,
 | 
					 | 
				
			||||||
                                     FOREIGN KEY (status_id)
 | 
					 | 
				
			||||||
                                         REFERENCES status (id)
 | 
					 | 
				
			||||||
                                         ON UPDATE NO ACTION
 | 
					 | 
				
			||||||
                                         ON DELETE NO ACTION
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
INSERT INTO status (id, name, comment)
 | 
					 | 
				
			||||||
VALUES(0, 'New', 'Freshly uploaded file');
 | 
					 | 
				
			||||||
INSERT INTO status (id, name, comment)
 | 
					 | 
				
			||||||
VALUES(1, 'Processing', '');
 | 
					 | 
				
			||||||
INSERT INTO status (id, name, comment)
 | 
					 | 
				
			||||||
VALUES(2, 'Denied', 'File download was denied');
 | 
					 | 
				
			||||||
INSERT INTO status (id, name, comment)
 | 
					 | 
				
			||||||
VALUES(3, 'Granted', 'File download was granted');
 | 
					 | 
				
			||||||
| 
						 | 
					@ -2,11 +2,19 @@
 | 
				
			||||||
<div class="starter-template">
 | 
					<div class="starter-template">
 | 
				
			||||||
    <div class="page-header">
 | 
					    <div class="page-header">
 | 
				
			||||||
        <h1>Files</h1>
 | 
					        <h1>Files</h1>
 | 
				
			||||||
        <p>List of all files and their Status</p>
 | 
					        <p>List of all files and their Status. Currently, can only search for ID and Name</p>
 | 
				
			||||||
        <p>Total Files: {{.totalEntries}}</p>
 | 
					        <p>Total Files: {{.totalEntries}}</p>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="form-group">
 | 
				
			||||||
 | 
					       <form action="/file/" method="GET">
 | 
				
			||||||
 | 
					           <label for="name">Name</label>
 | 
				
			||||||
 | 
					           <input type="text" name="name" id="name" class="form-control" required>
 | 
				
			||||||
 | 
					           <label for="id">ID</label>
 | 
				
			||||||
 | 
					           <input type="number" name="id" id="id" class="form-control" required>
 | 
				
			||||||
 | 
					           <input type="submit" value="Search" class="btn btn-primary">
 | 
				
			||||||
 | 
					       </form>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div id="pagination"></div>
 | 
					 | 
				
			||||||
<table class="table table-hover">
 | 
					<table class="table table-hover">
 | 
				
			||||||
    <tbody>
 | 
					    <tbody>
 | 
				
			||||||
    <tr>
 | 
					    <tr>
 | 
				
			||||||
| 
						 | 
					@ -35,43 +43,5 @@
 | 
				
			||||||
</table>
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
    // Generate pagination
 | 
					 | 
				
			||||||
    function generatePagination(itemsPerPage, totalItems) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Calculate total pages
 | 
					 | 
				
			||||||
        let totalPages = Math.ceil(totalItems / itemsPerPage);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let paginationHtml = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Loop to generate page links
 | 
					 | 
				
			||||||
        for (let i = 1; i <= totalPages; i++) {
 | 
					 | 
				
			||||||
            paginationHtml += `
 | 
					 | 
				
			||||||
      <li class="page-item">
 | 
					 | 
				
			||||||
        <a class="page-link" href="#">${i}</a>
 | 
					 | 
				
			||||||
      </li>
 | 
					 | 
				
			||||||
    `;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Output pagination
 | 
					 | 
				
			||||||
        $('#pagination').html(paginationHtml);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Usage
 | 
					 | 
				
			||||||
    let itemsPerPage = {{.count}};
 | 
					 | 
				
			||||||
    let totalItems = {{.totalEntries}};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    generatePagination(itemsPerPage, totalItems);
 | 
					 | 
				
			||||||
    $('#pagination').on('click', 'a', function(e){
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Get clicked page
 | 
					 | 
				
			||||||
        let page = $(this).text();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Load data for page
 | 
					 | 
				
			||||||
        loadProducts(page);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        e.preventDefault();
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
{{template "footer.gohtml"}}
 | 
					{{template "footer.gohtml"}}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,5 @@
 | 
				
			||||||
        <footer class="footer">
 | 
					        <footer class="footer">
 | 
				
			||||||
            <p>Copyright © Johannnes Bülow <a href="https://www.jmbit.de/">www.jmbit.de</a></p>
 | 
					            <p>Copyright © Johannes Bülow <a href="https://www.jmbit.de/">www.jmbit.de</a></p>
 | 
				
			||||||
 | 
					 | 
				
			||||||
        </footer>
 | 
					        </footer>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        </div> <!-- End of main container -->
 | 
					        </div> <!-- End of main container -->
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										22
									
								
								templates/login.gohtml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								templates/login.gohtml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					{{template "header.gohtml"}}
 | 
				
			||||||
 | 
					<div class="starter-template">
 | 
				
			||||||
 | 
					    <div class="page-header">
 | 
				
			||||||
 | 
					        <h1>{{ .title }}</h1>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="row">
 | 
				
			||||||
 | 
					        <div class="col-md-6">
 | 
				
			||||||
 | 
					            <h2>Login</h2>
 | 
				
			||||||
 | 
					            <div class="form-group">
 | 
				
			||||||
 | 
					                <form action="/login" method="POST">
 | 
				
			||||||
 | 
					                    <label for="name">Enter your Username</label>
 | 
				
			||||||
 | 
					                    <input type="text" name="name" id="name" class="form-control" required>
 | 
				
			||||||
 | 
					                    <label for="password">Password</label>
 | 
				
			||||||
 | 
					                    <input type="password" name="password" id="password" class="form-control" required>
 | 
				
			||||||
 | 
					                    <input type="submit" value="Login" class="btn btn-primary">
 | 
				
			||||||
 | 
					                </form>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{{template "footer.gohtml"}}
 | 
				
			||||||
							
								
								
									
										57
									
								
								web/auth/hashPassword.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								web/auth/hashPassword.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,57 @@
 | 
				
			||||||
 | 
					package auth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.jmbit.de/filegate/filegate/database"
 | 
				
			||||||
 | 
						"github.com/gin-contrib/sessions"
 | 
				
			||||||
 | 
						"golang.org/x/crypto/bcrypt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// adapted from https://www.gregorygaines.com/blog/how-to-properly-hash-and-salt-passwords-in-golang-bcrypt/
 | 
				
			||||||
 | 
					// hashPassword Hash password using bcrypt and
 | 
				
			||||||
 | 
					func hashPassword(password string) (string, error) {
 | 
				
			||||||
 | 
						// Convert password string to byte slice
 | 
				
			||||||
 | 
						var passwordBytes = []byte(password)
 | 
				
			||||||
 | 
						// Hash password with Bcrypt's default cost
 | 
				
			||||||
 | 
						hashedPasswordBytes, err := bcrypt.
 | 
				
			||||||
 | 
							GenerateFromPassword(passwordBytes, bcrypt.DefaultCost)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return string(hashedPasswordBytes), err
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// doPasswordsMatch Check if two passwords match using Bcrypt's CompareHashAndPassword
 | 
				
			||||||
 | 
					// which return nil on success and an error on failure.
 | 
				
			||||||
 | 
					func doPasswordsMatch(hashedPassword, currPassword string) bool {
 | 
				
			||||||
 | 
						err := bcrypt.CompareHashAndPassword(
 | 
				
			||||||
 | 
							[]byte(hashedPassword), []byte(currPassword))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return err == nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func storePasswordHash(username string, hash string) error {
 | 
				
			||||||
 | 
						err := database.UpdatePassword(username, hash)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// checkPassword checks if the password correctly correlates to the password hash stored in the Database
 | 
				
			||||||
 | 
					func checkPassword(username string, password string, session sessions.Session) error {
 | 
				
			||||||
 | 
						var user database.User
 | 
				
			||||||
 | 
						user, err := database.GetUser(username)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if doPasswordsMatch(user.PassHash, password) {
 | 
				
			||||||
 | 
							session.Set("username", username)
 | 
				
			||||||
 | 
							session.Set("accessLevel", user.Role.AccessLevel)
 | 
				
			||||||
 | 
							session.Set("isLoggedIn", true)
 | 
				
			||||||
 | 
							err := session.Save()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										28
									
								
								web/auth/login.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								web/auth/login.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,28 @@
 | 
				
			||||||
 | 
					package auth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gin-contrib/sessions"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetLogin(c *gin.Context) {
 | 
				
			||||||
 | 
						content := gin.H{
 | 
				
			||||||
 | 
							"title": "Home",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.HTML(http.StatusOK, "index.gohtml", content)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PostLogin(c *gin.Context) {
 | 
				
			||||||
 | 
						session := sessions.Default(c)
 | 
				
			||||||
 | 
						name := c.PostForm("name")
 | 
				
			||||||
 | 
						password := c.PostForm("password")
 | 
				
			||||||
 | 
						err := checkPassword(name, password, session)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							c.HTML(http.StatusBadRequest, "error.gohtml", gin.H{"title": "Error", "message": err})
 | 
				
			||||||
 | 
							log.Println(err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								web/auth/middleware.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								web/auth/middleware.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,31 @@
 | 
				
			||||||
 | 
					package auth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"github.com/gin-contrib/sessions"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AuthMiddleware deals with checking authentication and authorization (Is the user logged in and permitted to see/do something)
 | 
				
			||||||
 | 
					func AuthMiddleware(requiredLevel int) gin.HandlerFunc {
 | 
				
			||||||
 | 
						return func(c *gin.Context) {
 | 
				
			||||||
 | 
							session := sessions.Default(c)
 | 
				
			||||||
 | 
							isLoggedIn := session.Get("isLoggedIn")
 | 
				
			||||||
 | 
							accessLevel := session.Get("accessLevel")
 | 
				
			||||||
 | 
							if isLoggedIn != true {
 | 
				
			||||||
 | 
								c.Redirect(http.StatusFound, "/login")
 | 
				
			||||||
 | 
								// Not logged in, abort
 | 
				
			||||||
 | 
								c.Abort()
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if accessLevelValue, ok := accessLevel.(int); ok {
 | 
				
			||||||
 | 
								if accessLevelValue < requiredLevel {
 | 
				
			||||||
 | 
									c.HTML(http.StatusUnauthorized, "error.gohtml", gin.H{"title": "Not authorized", "message": "You are not authorized to do this action"})
 | 
				
			||||||
 | 
									c.Abort()
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// Logged in and authorized, continue
 | 
				
			||||||
 | 
							c.Next()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,13 +1,13 @@
 | 
				
			||||||
package web
 | 
					package browser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"git.jmbit.de/filegate/filegate/podthing"
 | 
						"git.jmbit.de/filegate/filegate/pods"
 | 
				
			||||||
	"github.com/google/uuid"
 | 
						"github.com/google/uuid"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewBrowser() (string, string, string) {
 | 
					func NewBrowser() (string, string, string) {
 | 
				
			||||||
	passwd := uuid.NewString()
 | 
						passwd := uuid.NewString()
 | 
				
			||||||
	folderId := uuid.NewString()
 | 
						folderId := uuid.NewString()
 | 
				
			||||||
	browserPod := podthing.CreateDownloadContainer("user", passwd, folderId)
 | 
						browserPod := pods.CreateDownloadContainer("user", passwd, folderId)
 | 
				
			||||||
	return browserPod, folderId, passwd
 | 
						return browserPod, folderId, passwd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -17,14 +17,17 @@ func GetFileList(c *gin.Context) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Println(err)
 | 
							log.Println(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	totalEntries := database.CountFilesEntries()
 | 
						fileList, err := database.GetFileList(page, count, c)
 | 
				
			||||||
	fileList := database.GetFileList(page, count)
 | 
						lowestEntry := (page - 1) * count
 | 
				
			||||||
 | 
						highestEntry := page * count
 | 
				
			||||||
 | 
						fileListPage := fileList[lowestEntry:highestEntry]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	content := gin.H{
 | 
						content := gin.H{
 | 
				
			||||||
		"fileList":     fileList,
 | 
							"fileList":     fileListPage,
 | 
				
			||||||
		"error":        "",
 | 
							"error":        err,
 | 
				
			||||||
		"page":         page,
 | 
							"page":         page,
 | 
				
			||||||
		"count":        count,
 | 
							"count":        count,
 | 
				
			||||||
		"totalEntries": totalEntries,
 | 
							"totalEntries": len(fileList),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c.HTML(http.StatusOK, "filelist.gohtml", content)
 | 
						c.HTML(http.StatusOK, "filelist.gohtml", content)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								web/routes.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								web/routes.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					package web
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.jmbit.de/filegate/filegate/web/auth"
 | 
				
			||||||
 | 
						"github.com/gin-gonic/gin"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetRoutes(router *gin.Engine) *gin.Engine {
 | 
				
			||||||
 | 
						router.GET("/", GetIndex)
 | 
				
			||||||
 | 
						router.GET("/file/:id", GetFileView)
 | 
				
			||||||
 | 
						router.GET("/file/", GetFileList)
 | 
				
			||||||
 | 
						router.POST("/file/new", PostSubmitFileUrl)
 | 
				
			||||||
 | 
						router.POST("/file/upload", PostUploadFile)
 | 
				
			||||||
 | 
						router.GET("/browser/:id/")
 | 
				
			||||||
 | 
						router.GET("/login", auth.GetLogin)
 | 
				
			||||||
 | 
						return router
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								web/session.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								web/session.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					package web
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue