2020-06-07 20:28:32 +03:00
package routes
import (
"fmt"
"github.com/gorilla/schema"
2020-10-09 22:37:16 +03:00
conf "github.com/muety/wakapi/config"
2020-06-07 20:28:32 +03:00
"github.com/muety/wakapi/models"
"github.com/muety/wakapi/services"
"github.com/muety/wakapi/utils"
2020-11-06 19:09:41 +03:00
"log"
2020-06-07 20:28:32 +03:00
"net/http"
2020-06-07 20:58:06 +03:00
"net/url"
2020-10-27 00:34:50 +03:00
"strconv"
2020-06-07 20:28:32 +03:00
)
type SettingsHandler struct {
2020-11-01 22:14:10 +03:00
config * conf . Config
userSrvc * services . UserService
2020-11-06 19:09:41 +03:00
summarySrvc * services . SummaryService
aggregationSrvc * services . AggregationService
2020-11-01 22:14:10 +03:00
languageMappingSrvc * services . LanguageMappingService
2020-06-07 20:28:32 +03:00
}
var credentialsDecoder = schema . NewDecoder ( )
2020-11-06 19:09:41 +03:00
func NewSettingsHandler ( userService * services . UserService , summaryService * services . SummaryService , aggregationService * services . AggregationService , languageMappingService * services . LanguageMappingService ) * SettingsHandler {
2020-06-07 20:28:32 +03:00
return & SettingsHandler {
2020-11-01 22:14:10 +03:00
config : conf . Get ( ) ,
2020-11-06 19:09:41 +03:00
summarySrvc : summaryService ,
aggregationSrvc : aggregationService ,
2020-11-01 22:14:10 +03:00
languageMappingSrvc : languageMappingService ,
userSrvc : userService ,
2020-06-07 20:28:32 +03:00
}
}
func ( h * SettingsHandler ) GetIndex ( w http . ResponseWriter , r * http . Request ) {
if h . config . IsDev ( ) {
loadTemplates ( )
}
2020-09-12 17:09:23 +03:00
user := r . Context ( ) . Value ( models . UserKey ) . ( * models . User )
2020-11-01 22:14:10 +03:00
mappings , _ := h . languageMappingSrvc . GetByUser ( user . ID )
2020-09-12 17:09:23 +03:00
data := map [ string ] interface { } {
2020-11-01 22:14:10 +03:00
"User" : user ,
"LanguageMappings" : mappings ,
"Success" : r . FormValue ( "success" ) ,
"Error" : r . FormValue ( "error" ) ,
2020-09-12 17:09:23 +03:00
}
2020-10-09 22:37:16 +03:00
templates [ conf . SettingsTemplate ] . Execute ( w , data )
2020-06-07 20:28:32 +03:00
}
func ( h * SettingsHandler ) PostCredentials ( w http . ResponseWriter , r * http . Request ) {
if h . config . IsDev ( ) {
loadTemplates ( )
}
user := r . Context ( ) . Value ( models . UserKey ) . ( * models . User )
var credentials models . CredentialsReset
if err := r . ParseForm ( ) ; err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "missing parameters" ) ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
return
}
if err := credentialsDecoder . Decode ( & credentials , r . PostForm ) ; err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "missing parameters" ) ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
return
}
2020-10-16 17:11:14 +03:00
if ! utils . CompareBcrypt ( user . Password , credentials . PasswordOld , h . config . Security . PasswordSalt ) {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "invalid credentials" ) ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
return
}
if ! credentials . IsValid ( ) {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "invalid parameters" ) ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
return
}
user . Password = credentials . PasswordNew
2020-10-16 17:11:14 +03:00
if hash , err := utils . HashBcrypt ( user . Password , h . config . Security . PasswordSalt ) ; err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "internal server error" ) ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
return
2020-10-16 17:11:14 +03:00
} else {
user . Password = hash
2020-06-07 20:28:32 +03:00
}
if _ , err := h . userSrvc . Update ( user ) ; err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "internal server error" ) ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
return
}
login := & models . Login {
Username : user . ID ,
Password : user . Password ,
}
2020-10-04 11:37:38 +03:00
encoded , err := h . config . Security . SecureCookie . Encode ( models . AuthCookieKey , login )
2020-06-07 20:28:32 +03:00
if err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "internal server error" ) ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
return
}
cookie := & http . Cookie {
Name : models . AuthCookieKey ,
Value : encoded ,
Path : "/" ,
2020-10-04 11:37:38 +03:00
Secure : ! h . config . Security . InsecureCookies ,
2020-06-07 20:28:32 +03:00
HttpOnly : true ,
}
http . SetCookie ( w , cookie )
2020-06-07 20:58:06 +03:00
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?success=%s" , h . config . Server . BasePath , url . QueryEscape ( "password was updated successfully" ) ) , http . StatusFound )
2020-10-25 09:22:10 +03:00
}
2020-11-01 22:14:10 +03:00
func ( h * SettingsHandler ) DeleteLanguageMapping ( w http . ResponseWriter , r * http . Request ) {
2020-10-25 09:22:10 +03:00
if h . config . IsDev ( ) {
loadTemplates ( )
}
user := r . Context ( ) . Value ( models . UserKey ) . ( * models . User )
2020-11-01 22:14:10 +03:00
id , err := strconv . Atoi ( r . PostFormValue ( "mapping_id" ) )
2020-10-25 09:22:10 +03:00
if err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "could not delete mapping" ) ) , http . StatusFound )
2020-10-25 09:22:10 +03:00
return
}
2020-11-01 22:14:10 +03:00
mapping := & models . LanguageMapping {
ID : uint ( id ) ,
2020-10-25 09:22:10 +03:00
UserID : user . ID ,
2020-10-27 00:34:50 +03:00
}
2020-11-01 18:56:36 +03:00
2020-11-01 22:14:10 +03:00
err = h . languageMappingSrvc . Delete ( mapping )
2020-11-01 18:56:36 +03:00
if err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "could not delete mapping" ) ) , http . StatusFound )
2020-11-01 18:56:36 +03:00
return
}
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?success=%s" , h . config . Server . BasePath , url . QueryEscape ( "mapping deleted successfully" ) ) , http . StatusFound )
2020-10-25 09:22:10 +03:00
}
2020-11-06 19:09:41 +03:00
func ( h * SettingsHandler ) PostLanguageMapping ( w http . ResponseWriter , r * http . Request ) {
2020-10-25 09:22:10 +03:00
if h . config . IsDev ( ) {
loadTemplates ( )
}
user := r . Context ( ) . Value ( models . UserKey ) . ( * models . User )
extension := r . PostFormValue ( "extension" )
language := r . PostFormValue ( "language" )
if extension [ 0 ] == '.' {
extension = extension [ 1 : ]
}
2020-11-01 22:14:10 +03:00
mapping := & models . LanguageMapping {
2020-10-27 00:34:50 +03:00
UserID : user . ID ,
2020-10-25 09:22:10 +03:00
Extension : extension ,
2020-10-27 00:34:50 +03:00
Language : language ,
}
2020-10-25 09:22:10 +03:00
2020-11-01 22:14:10 +03:00
if _ , err := h . languageMappingSrvc . Create ( mapping ) ; err != nil {
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "mapping already exists" ) ) , http . StatusFound )
2020-10-25 09:22:10 +03:00
return
}
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?success=%s" , h . config . Server . BasePath , url . QueryEscape ( "mapping added successfully" ) ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
}
func ( h * SettingsHandler ) PostResetApiKey ( w http . ResponseWriter , r * http . Request ) {
if h . config . IsDev ( ) {
loadTemplates ( )
}
2020-06-07 20:58:06 +03:00
user := r . Context ( ) . Value ( models . UserKey ) . ( * models . User )
if _ , err := h . userSrvc . ResetApiKey ( user ) ; err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "internal server error" ) ) , http . StatusFound )
2020-06-07 20:58:06 +03:00
return
}
msg := url . QueryEscape ( fmt . Sprintf ( "your new api key is: %s" , user . ApiKey ) )
2020-10-04 11:37:38 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?success=%s" , h . config . Server . BasePath , msg ) , http . StatusFound )
2020-06-07 20:28:32 +03:00
}
2020-09-12 17:09:23 +03:00
func ( h * SettingsHandler ) PostToggleBadges ( w http . ResponseWriter , r * http . Request ) {
if h . config . IsDev ( ) {
loadTemplates ( )
}
user := r . Context ( ) . Value ( models . UserKey ) . ( * models . User )
if _ , err := h . userSrvc . ToggleBadges ( user ) ; err != nil {
2020-11-01 22:14:10 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "internal server error" ) ) , http . StatusFound )
2020-09-12 17:09:23 +03:00
return
}
2020-10-04 11:37:38 +03:00
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings" , h . config . Server . BasePath ) , http . StatusFound )
2020-09-12 17:09:23 +03:00
}
2020-11-06 19:09:41 +03:00
func ( h * SettingsHandler ) PostRegenerateSummaries ( w http . ResponseWriter , r * http . Request ) {
if h . config . IsDev ( ) {
loadTemplates ( )
}
user := r . Context ( ) . Value ( models . UserKey ) . ( * models . User )
log . Printf ( "clearing summaries for user '%s'\n" , user . ID )
if err := h . summarySrvc . DeleteByUser ( user . ID ) ; err != nil {
log . Printf ( "failed to clear summaries: %v\n" , err )
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "failed to delete old summaries" ) ) , http . StatusFound )
return
}
if err := h . aggregationSrvc . Run ( map [ string ] bool { user . ID : true } ) ; err != nil {
log . Printf ( "failed to regenerate summaries: %v\n" , err )
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?error=%s" , h . config . Server . BasePath , url . QueryEscape ( "failed to generate aggregations" ) ) , http . StatusFound )
return
}
http . Redirect ( w , r , fmt . Sprintf ( "%s/settings?success=%s" , h . config . Server . BasePath , url . QueryEscape ( "summaries are being regenerated – this may take a few second" ) ) , http . StatusFound )
}