Browse Source

Implement login

master
Dylan Baker 3 years ago
parent
commit
4734868874
4 changed files with 114 additions and 23 deletions
  1. 60
    7
      src/main.rs
  2. 18
    16
      templates/index.html
  3. 14
    0
      templates/layout.html
  4. 22
    0
      templates/login.html

+ 60
- 7
src/main.rs View File

@@ -23,6 +23,12 @@ struct Post {
23 23
     date: String,
24 24
 }
25 25
 
26
+#[derive(Debug, Serialize, Deserialize)]
27
+struct User {
28
+    username: String,
29
+    password: String,
30
+}
31
+
26 32
 impl Post {
27 33
     fn save(&mut self) -> std::io::Result<()> {
28 34
         let mut path: PathBuf = get_posts_directory()?;
@@ -99,25 +105,72 @@ async fn main() -> std::io::Result<()> {
99 105
         Ok(res)
100 106
     }));
101 107
 
102
-    app.at("/").get(|_| async {
108
+    app.with(tide::sessions::SessionMiddleware::new(
109
+        tide::sessions::MemoryStore::new(),
110
+        std::env::var("TIDE_SECRET")
111
+            .expect(
112
+                "Please provide a TIDE_SECRET value of at \
113
+                      least 32 bytes in order to run this example",
114
+            )
115
+            .as_bytes(),
116
+    ));
117
+
118
+    app.at("/").get(|req: tide::Request<()>| async move {
103 119
         let tera = Tera::new("templates/**/*.html")?;
104 120
         let posts = read_all_posts().await?;
105 121
         let mut context = Context::new();
106 122
         context.insert("posts", &posts);
123
+        let logged_in: bool = req.session().get("logged_in").unwrap_or(false);
124
+        context.insert("logged_in", &logged_in);
107 125
         let html = tera.render("index.html", &context)?;
108 126
         Ok(Body::from_string(html))
109 127
     });
110 128
 
111 129
     app.at("/posts")
112 130
         .post(|mut req: tide::Request<()>| async move {
113
-            let mut post: Post = req.body_form().await?;
114
-            post.id = Uuid::new_v4().to_string();
115
-            post.date = Local::now().date().naive_local().to_string();
116
-            post.body = post.body.trim().to_owned();
117
-            post.save()?;
118
-            Ok(tide::Redirect::new("/"))
131
+            let logged_in: bool = req.session().get("logged_in").unwrap_or(false);
132
+            if !logged_in {
133
+                Ok(tide::Redirect::new("/login"))
134
+            } else {
135
+                let mut post: Post = req.body_form().await?;
136
+                post.id = Uuid::new_v4().to_string();
137
+                post.date = Local::now().date().naive_local().to_string();
138
+                post.body = post.body.trim().to_owned();
139
+                post.save()?;
140
+                Ok(tide::Redirect::new("/"))
141
+            }
119 142
         });
120 143
 
144
+    app.at("/login").get(|req: tide::Request<()>| async move {
145
+        let tera = Tera::new("templates/**/*.html")?;
146
+        let mut context = Context::new();
147
+        let logged_in: bool = req.session().get("logged_in").unwrap_or(false);
148
+        context.insert("logged_in", &logged_in);
149
+        let html = tera.render("login.html", &context)?;
150
+        Ok(Body::from_string(html))
151
+    }).post(|mut req: tide::Request<()>| async move {
152
+        let logged_in: bool = req.session().get("logged_in").unwrap_or(false);
153
+        if logged_in {
154
+            return Ok(tide::Redirect::new("/"));
155
+        }
156
+
157
+        let username = env::var("ADMIN_USERNAME")?;
158
+        let password = env::var("ADMIN_PASSWORD")?;
159
+        let user: User = req.body_form().await?;
160
+        if user.username == username && user.password == password {
161
+            req.session_mut().insert("logged_in", true)?;
162
+            Ok(tide::Redirect::new("/"))
163
+        } else {
164
+            Ok(tide::Redirect::new("/login"))
165
+        }
166
+    });
167
+
168
+    app.at("/logout").get(|mut req: tide::Request<()>| async move {
169
+        req.session_mut().remove("logged_in");
170
+        req.session_mut().insert("logged_in", false)?;
171
+        Ok(tide::Redirect::new("/"))
172
+    });
173
+
121 174
     app.listen("127.0.0.1:8080").await?;
122 175
 
123 176
     Ok(())

+ 18
- 16
templates/index.html View File

@@ -1,20 +1,22 @@
1 1
 {% extends "layout.html" %} {% block content %}
2
-<h1 class="heading">Admin</h1>
3
-<form class="form" method="POST" action="/posts">
4
-  <input type="hidden" name="id" />
5
-  <input type="hidden" name="date" />
6
-  <div class="form__field">
7
-    <label for="title" class="form__label">Title</label>
8
-    <input class="form__text-field" type="text" name="title" required />
9
-  </div>
10
-  <div class="form__field">
11
-    <label for="body" class="form__label">Body</label>
12
-    <textarea class="form__textarea" name="body" required></textarea>
13
-  </div>
14
-  <div class="form__field">
15
-    <input class="form__button" type="submit" value="Post" />
16
-  </div>
17
-</form>
2
+{% if logged_in %}
3
+  <h1 class="heading">New Post</h1>
4
+  <form class="form" method="POST" action="/posts">
5
+    <input type="hidden" name="id" />
6
+    <input type="hidden" name="date" />
7
+    <div class="form__field">
8
+      <label for="title" class="form__label">Title</label>
9
+      <input class="form__text-field" type="text" name="title" required />
10
+    </div>
11
+    <div class="form__field">
12
+      <label for="body" class="form__label">Body</label>
13
+      <textarea class="form__textarea" name="body" required></textarea>
14
+    </div>
15
+    <div class="form__field">
16
+      <input class="form__button" type="submit" value="Post" />
17
+    </div>
18
+  </form>
19
+{% endif %}
18 20
 
19 21
 <div class="posts">
20 22
   {% for post in posts %}

+ 14
- 0
templates/layout.html View File

@@ -18,6 +18,15 @@
18 18
         font-size: 12px;
19 19
       }
20 20
 
21
+      a {
22
+        color: #383e37;
23
+      }
24
+
25
+      a:hover {
26
+        text-decoration: none;
27
+      }
28
+
29
+      .header,
21 30
       .container {
22 31
         margin: auto;
23 32
         max-width: 800px;
@@ -93,6 +102,11 @@
93 102
     </style>
94 103
   </head>
95 104
   <body>
105
+    <header class="header">
106
+      {% if logged_in %}
107
+        <a href="/logout">logout</a>
108
+      {% endif %}
109
+    </header>
96 110
     <div class="container">
97 111
       {% block content %} {% endblock %}
98 112
     </div>

+ 22
- 0
templates/login.html View File

@@ -0,0 +1,22 @@
1
+{% extends "layout.html" %} {% block content %}
2
+<h1 class="heading">Login</h1>
3
+<form class="form" method="POST" action="/login">
4
+  <div class="form__field">
5
+    <label for="username" class="form__label">Username</label>
6
+    <input class="form__text-field" type="text" name="username" required />
7
+  </div>
8
+  <div class="form__field">
9
+    <label for="password" class="form__label">Password</label>
10
+    <input class="form__text-field" type="password" name="password" required />
11
+  </div>
12
+  {% if error %}
13
+    <div class="error">
14
+      <h1 class="error__heading">Error:</h1>
15
+      <p class="error__message">{{ error }}</p>
16
+    </div>
17
+  {% endif %}
18
+  <div class="form__field">
19
+    <input class="form__button" type="submit" value="Login" />
20
+  </div>
21
+</form>
22
+{% endblock %}

Loading…
Cancel
Save