kopia lustrzana https://codeberg.org/nmkj/audon
fix cookie options
rodzic
059ab019d6
commit
da13f2f55c
|
@ -15,6 +15,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
server: "",
|
||||
serverErr: "",
|
||||
};
|
||||
},
|
||||
validations() {
|
||||
|
@ -31,7 +32,11 @@ export default {
|
|||
computed: {
|
||||
serverErrors() {
|
||||
const errors = this.v$.server.$errors;
|
||||
return _.map(errors, (e) => e.$message);
|
||||
const messages = _.map(errors, (e) => e.$message);
|
||||
if (this.serverErr !== "") {
|
||||
messages.push(this.serverErr);
|
||||
}
|
||||
return messages;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
@ -40,12 +45,25 @@ export default {
|
|||
if (!isFormCorrect) {
|
||||
return;
|
||||
}
|
||||
const response = await axios.postForm("/api/login", { server: this.server });
|
||||
if (response.status === 201) {
|
||||
// this.$router.push(response.data)
|
||||
location.assign(response.data)
|
||||
try {
|
||||
const response = await axios.postForm("/api/login", {
|
||||
server: this.server,
|
||||
});
|
||||
if (response.status === 201) {
|
||||
// this.$router.push(response.data)
|
||||
location.assign(response.data);
|
||||
this.serverErr = "";
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.response && error.response.status === 404) {
|
||||
this.serverErr = "サーバーが見つかりません"
|
||||
}
|
||||
}
|
||||
},
|
||||
onInput () {
|
||||
this.v$.server.$touch();
|
||||
this.serverErr = "";
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -60,8 +78,7 @@ export default {
|
|||
placeholder="mastodon.example"
|
||||
class="mb-2"
|
||||
:error-messages="serverErrors"
|
||||
@input="v$.server.$touch"
|
||||
@blur="v$.server.$touch"
|
||||
@update:model-value="onInput"
|
||||
clearable
|
||||
/>
|
||||
<v-btn block @click="onSubmit" :disabled="!v$.$dirty || v$.$error"
|
||||
|
|
|
@ -12,12 +12,13 @@ type (
|
|||
AppConfigBase
|
||||
Livekit *LivekitConfig
|
||||
MongoURL *url.URL
|
||||
Database *DBConfig
|
||||
}
|
||||
|
||||
AppConfigBase struct {
|
||||
Database *DBConfig
|
||||
SeesionSecret string `validate:"required,ascii"`
|
||||
LocalDomain string `validate:"required,hostname|hostname_port"`
|
||||
Environment string `validate:"printascii"`
|
||||
}
|
||||
|
||||
LivekitConfig struct {
|
||||
|
@ -60,6 +61,7 @@ func loadConfig(envname string) (*AppConfig, error) {
|
|||
basicConf := AppConfigBase{
|
||||
SeesionSecret: os.Getenv("SESSION_SECRET"),
|
||||
LocalDomain: os.Getenv("LOCAL_DOMAIN"),
|
||||
Environment: envname,
|
||||
}
|
||||
if basicConf.SeesionSecret == "" {
|
||||
basicConf.SeesionSecret = "dev"
|
||||
|
|
|
@ -11,6 +11,8 @@ services:
|
|||
MONGO_INITDB_ROOT_PASSWORD: example
|
||||
ports:
|
||||
- 27017:27017
|
||||
volumes:
|
||||
- db:/data/db
|
||||
|
||||
mongo-express:
|
||||
image: mongo-express
|
||||
|
@ -21,3 +23,16 @@ services:
|
|||
ME_CONFIG_MONGODB_ADMINUSERNAME: root
|
||||
ME_CONFIG_MONGODB_ADMINPASSWORD: example
|
||||
ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/
|
||||
|
||||
# redis:
|
||||
# restart: always
|
||||
# image: redis
|
||||
# healthcheck:
|
||||
# test: ['CMD', 'redis-cli', 'ping']
|
||||
# ports:
|
||||
# - 6379:6379
|
||||
# volumes:
|
||||
# - audon:/data
|
||||
|
||||
volumes:
|
||||
db:
|
||||
|
|
15
oauth.go
15
oauth.go
|
@ -14,19 +14,20 @@ import (
|
|||
)
|
||||
|
||||
func verifyTokenInSession(c echo.Context, sess *sessions.Session) (valid bool, err error) {
|
||||
mastConf, err := getSessionData(sess)
|
||||
data, err := getSessionData(sess)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if mastConf.MastodonConfig.AccessToken == "" {
|
||||
if data.MastodonConfig.AccessToken == "" {
|
||||
return false, nil
|
||||
}
|
||||
mastoClient := mastodon.NewClient(mastConf.MastodonConfig)
|
||||
mastoClient := mastodon.NewClient(data.MastodonConfig)
|
||||
|
||||
_, err = mastoClient.VerifyAppCredentials(c.Request().Context())
|
||||
acc, err := mastoClient.GetAccountCurrentUser(c.Request().Context())
|
||||
user, dbErr := findUserByID(c.Request().Context(), data.AudonID)
|
||||
|
||||
if err != nil {
|
||||
if err != nil || dbErr != nil || string(acc.ID) != user.RemoteID {
|
||||
return false, err
|
||||
}
|
||||
|
||||
|
@ -129,7 +130,7 @@ func oauthHandler(c echo.Context) (err error) {
|
|||
// return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
// }
|
||||
entropy := ulid.Monotonic(rand.Reader, 0)
|
||||
id, err := ulid.New(ulid.Timestamp(time.Now()), entropy)
|
||||
id, err := ulid.New(ulid.Timestamp(time.Now().UTC()), entropy)
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
|
@ -139,7 +140,7 @@ func oauthHandler(c echo.Context) (err error) {
|
|||
AudonID: data.AudonID,
|
||||
RemoteID: string(acc.ID),
|
||||
RemoteURL: acc.URL,
|
||||
CreatedAt: time.Now(),
|
||||
CreatedAt: time.Now().UTC(),
|
||||
}
|
||||
if _, insertErr := coll.InsertOne(c.Request().Context(), newUser); insertErr != nil {
|
||||
c.Logger().Error(insertErr)
|
||||
|
|
28
room.go
28
room.go
|
@ -45,33 +45,37 @@ func createRoomHandler(c echo.Context) (err error) {
|
|||
}
|
||||
room.Host = host
|
||||
|
||||
now := time.Now().UTC()
|
||||
if now.Sub(room.ScheduledAt) > 0 {
|
||||
room.ScheduledAt = now
|
||||
}
|
||||
|
||||
// If CoHosts are already registered, retrieve their AudonID
|
||||
for i, cohost := range room.CoHost {
|
||||
cohostUser, err := findUserByRemote(c.Request().Context(), cohost.RemoteID, cohost.RemoteURL)
|
||||
if err == nil {
|
||||
room.CoHost[i].AudonID = cohostUser.AudonID
|
||||
room.CoHost[i] = cohostUser
|
||||
}
|
||||
}
|
||||
|
||||
roomToken, err := getHostToken(room.RoomID, host.AudonID)
|
||||
if err != nil {
|
||||
c.Logger().Error(err)
|
||||
room.CreatedAt = now
|
||||
|
||||
coll := mainDB.Collection(COLLECTION_ROOM)
|
||||
if _, insertErr := coll.InsertOne(c.Request().Context(), room); insertErr != nil {
|
||||
c.Logger().Error(insertErr)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusCreated, roomToken)
|
||||
return c.String(http.StatusCreated, room.RoomID)
|
||||
}
|
||||
|
||||
func getHostToken(room, identity string) (string, error) {
|
||||
func getHostToken(room *Room) (string, error) {
|
||||
at := auth.NewAccessToken(mainConfig.Livekit.APIKey, mainConfig.Livekit.APISecret)
|
||||
grant := &auth.VideoGrant{
|
||||
Room: room,
|
||||
RoomJoin: true,
|
||||
RoomRecord: true,
|
||||
Room: room.RoomID,
|
||||
RoomJoin: true,
|
||||
}
|
||||
at.AddGrant(grant).
|
||||
SetIdentity(identity).
|
||||
SetValidFor(24 * time.Hour)
|
||||
at.AddGrant(grant).SetIdentity(room.Host.AudonID).SetValidFor(10 * time.Minute)
|
||||
|
||||
return at.ToJWT()
|
||||
}
|
||||
|
|
43
schema.go
43
schema.go
|
@ -19,21 +19,20 @@ type (
|
|||
|
||||
AudonUser struct {
|
||||
AudonID string `bson:"audon_id" json:"audon_id" validate:"alphanum"`
|
||||
RemoteID string `bson:"remote_id" json:"remote_id" validate:"alphanum"`
|
||||
RemoteID string `bson:"remote_id" json:"remote_id" validate:"printascii"`
|
||||
RemoteURL string `bson:"remote_url" json:"remote_url" validate:"url"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"created_at"`
|
||||
}
|
||||
|
||||
Room struct {
|
||||
RoomID string `bson:"room_id" json:"room_id" validate:"required,alphanum"`
|
||||
Title string `bson:"title" json:"title" validate:"required,alphanumunicode"`
|
||||
Description string `bson:"description" json:"description" validate:"alphanumunicode"`
|
||||
RoomID string `bson:"room_id" json:"room_id" validate:"required,printascii"`
|
||||
Title string `bson:"title" json:"title" validate:"required,printascii|multibyte"`
|
||||
Description string `bson:"description" json:"description" validate:"printascii|multibyte"`
|
||||
Host *AudonUser `bson:"host" json:"host"`
|
||||
CoHost []*AudonUser `bson:"cohost" json:"cohost"`
|
||||
FollowingOnly bool `bson:"following_only" json:"following_only" validate:"required"`
|
||||
FollowerOnly bool `bson:"follower_only" json:"follower_only" validate:"required"`
|
||||
InviteOnly bool `bson:"invite_only" json:"invite_only" validate:"required"`
|
||||
InviteToken string `bson:"invite_token" json:"invite_token" validate:"alphanum"`
|
||||
FollowingOnly bool `bson:"following_only" json:"following_only"`
|
||||
FollowerOnly bool `bson:"follower_only" json:"follower_only"`
|
||||
MutualOnly bool `bson:"mutual_only" json:"mutual_only"`
|
||||
ScheduledAt time.Time `bson:"scheduled_at" json:"scheduled_at"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"created_at"`
|
||||
}
|
||||
|
@ -47,12 +46,15 @@ const (
|
|||
func createIndexes(ctx context.Context) error {
|
||||
userColl := mainDB.Collection(COLLECTION_USER)
|
||||
userIndexes, err := userColl.Indexes().ListSpecifications(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(userIndexes) < 3 {
|
||||
_, err := userColl.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{{Key: "audon_id", Value: 1}},
|
||||
Options: options.Index().SetName("audon_id_1").SetUnique(true),
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{
|
||||
|
@ -66,7 +68,28 @@ func createIndexes(ctx context.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
return err
|
||||
roomColl := mainDB.Collection(COLLECTION_ROOM)
|
||||
roomIndexes, err := roomColl.Indexes().ListSpecifications(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(roomIndexes) < 3 {
|
||||
_, err := roomColl.Indexes().CreateMany(ctx, []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{{Key: "room_id", Value: 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: "host.audon_id", Value: 1}},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func findUserByRemote(ctx context.Context, remoteID, remoteURL string) (*AudonUser, error) {
|
||||
|
|
34
server.go
34
server.go
|
@ -56,15 +56,17 @@ func main() {
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
dbContext, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
backContext, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
dbClient, err := mongo.Connect(dbContext, options.Client().ApplyURI(mainConfig.MongoURL.String()))
|
||||
|
||||
// Setup database client
|
||||
dbClient, err := mongo.Connect(backContext, options.Client().ApplyURI(mainConfig.MongoURL.String()))
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
os.Exit(2)
|
||||
}
|
||||
mainDB = dbClient.Database(mainConfig.Database.Name)
|
||||
err = createIndexes(dbContext)
|
||||
err = createIndexes(backContext)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
os.Exit(3)
|
||||
|
@ -78,7 +80,23 @@ func main() {
|
|||
}
|
||||
e.Renderer = t
|
||||
e.Validator = &CustomValidator{validator: mainValidator}
|
||||
e.Use(session.Middleware(sessions.NewCookieStore([]byte(mainConfig.SeesionSecret))))
|
||||
cookieStore := sessions.NewCookieStore([]byte(mainConfig.SeesionSecret))
|
||||
cookieStore.Options = &sessions.Options{
|
||||
Path: "/",
|
||||
Domain: mainConfig.LocalDomain,
|
||||
MaxAge: 86400 * 30,
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteStrictMode,
|
||||
Secure: true,
|
||||
}
|
||||
if mainConfig.Environment == "development" {
|
||||
cookieStore.Options.Domain = ""
|
||||
cookieStore.Options.SameSite = http.SameSiteNoneMode
|
||||
cookieStore.Options.Secure = false
|
||||
cookieStore.Options.MaxAge = 3600 * 24
|
||||
cookieStore.Options.HttpOnly = false
|
||||
}
|
||||
e.Use(session.Middleware(cookieStore))
|
||||
// e.Use(middleware.CSRFWithConfig(middleware.CSRFConfig{
|
||||
// CookiePath: "/",
|
||||
// TokenLookup: "header:X-XSRF-TOKEN",
|
||||
|
@ -164,14 +182,6 @@ func getSession(c echo.Context) (sess *sessions.Session, err error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
sess.Options = &sessions.Options{
|
||||
Path: "/",
|
||||
MaxAge: 0,
|
||||
HttpOnly: true,
|
||||
SameSite: http.SameSiteStrictMode,
|
||||
Secure: true,
|
||||
}
|
||||
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue