Panel admina w katalogu admin/

Witam,

Pytanie: Prosze o Wasze sugestie jak stosować Modele (np. User) w kontrolerach z przestrzenią nazwa (np. Admin:UserController) - potrzebne do panelu admina

mam pewien problem, który dotyczy bardziej pomysłu na zrobienie panelu admina katalogu admin.
Tworze aplikacje w RoR, która ma być forum internetowym zarządzalnym z konkretnym panelem admina. Pomyślałem, że dla dla usera z rolą admina czy moderatora można funkcje administratorskie typu ‘usun, edytuj, zablokuj’ itd. wrzucić normalnie na frontend, oczywiscie metody dostepne tylko po zatwierdzniu auoryzacji admina.
Przydałby się jednak jeszcze backend, panel admina (inny layout, dodawanie userow, ostrzezenia, przenoszenie tematow - wszystkie te funkcjonalnosci, ktore raczej ciezko zmiescic na froncie). Zacząłem więc używac katalogu admin/ i przestrzeni nazw dla kontrolerów. Wszystko ładnie działało, dopóki nie napotkałem na błąd, który okazał błędem wewnętrznym.

Mianowicie… Uzywam załózmy controllera Admin::UserController < Admin::BaseController , Base kontroller dziedziczy po Application. Czyli standardowe użycie. Teraz pierwsze co zrobilem, to zastosowalem generator rusztowania. Wszystko ladnie mi powstało, w katalogach jak powinno sie znajdować. Tylko, że ja już mam model dla Userów, zatem nie potrzebuje Admin::User. W kontrolerze Admin::UserController zamieniam modele z Admin::User na User. Wydaje się, że wszystko ładnie będzie działać. Do routingu dla admina używałem tego:

map.namespace(:admin) do |admin| admin.resources :photos,  :has_many => { :tags, :ratings} end

. Później nawet juz probowalem tak, jak polecał @radarek

[code]Kod: ruby

  1. generowanie:

  2. ./script/generate controller ‘admin/products’

  3. usuwanie

  4. ./script/generate controller ‘admin/products’

  5. przekierowanie

  6. redirect_to :controller => ‘admin/products’, :action => ‘list’

  7. named routes

  8. routes.rb

  9. map.admin_products ‘admin/products/:action/:id’, :controller => ‘admin/products’

  10. wygenerowane metody

  11. admin_products_path

  12. admin_products_url

  13. itp[/code]

Jednak jest problem przy <%= form_for(@user) … %> Rusztowanie samo tworzy sobie redirecty, linki przy pomocy obiektu modelu @user. Z racji, ze uzywam kontrollera Admin:userController to form_for sam generuje przy wysłaniu posta params[:admin_user] a nie params[:user]. Tutaj kiedy chce odebrac params[:user] to krzyczy ze jest nil.

Zatem probowalem dalej. Skoro Admin::UserController tak bardzo sie domaga tego, zatem wrocilem do uzywania modeli z przestenia nazw. W modelu Admin::User zrobilem dziedziczenie z User (nie potrzbuje tabeli admin_users w bazie). Ładnie wszystko idzie, do momentu wysłania posta z formularza /new.erb. Wtedy mam błąd o jakims przeładowaniu metod w stacku, czy cos takiego. Ogólnie pluje się o to, ze dziedzicze… Znalazlem opis na jakim zagr blogu. Gosciu tlumaczyl, ze mozna spokonie zrobic <%= form_for @user.becomes(User)… %> czyli cos a’la zrzutowanie obiektu do User. Tylko, ze wtedy psuje mi sie caly routing (linki). Opisał to jako wew problem, ktory bedzie naprawiony w v. 2.4 . Mam z tym ciągłe problemy, bo co chwila coś się wysypuje. Macie jakiś pomysł na obejscie tego?

Nie da sie tego ogranąć normalnie?

Moje prosby i pytania:
W jaki sposob to shackować?

Może ktoś z Was robił coś takiego kiedyś i z doświadczenia wie, ze inne rozwiązanie jest lepsze. Może jakoś inaczej rozwiązać ten problem. Wiem, ze moge tez olać namespace’y i tworzyc tak, jak opisane jest tu: http://www.caboo.se/articles/2006/07/01/if-your-models-arent-namespaced-why-should-your-controllers-be-or-how-i-learned-to-stop-worrying-and-love-the-crud , ale mimo wszystko fajnie byłoby mieć ten panel admina oddzielnie

Pozdrawiam i czekam na odp.

Możesz użyć namespace wyłącznie w kontrolerach, modele zostawić w spokoju i po prostu dodać do formularzy ścieżki czyli np dla edycji:

<%= form_for @user, :user, :url => admin_user_path( @user ), :html => { :method => :put } do |f| %>

Wykorzystujemy to w jednym projekcie i działa bez zarzutu.

Sprobuje w ten sposób na pewno. Dzieki @tjeden :slight_smile:
Tylko z racji, że jest to ważna dla mnie aplikacja (praca mgr), chcę skorzystać z jak największej ilości magii dostępnej w Railsach (pokazać wszystko to, co jest w nim najlepsze).
Jakieś kolejne pomysły?

Mając model User i namespace kontrolera admin, spróbuj zbudować formularz w ten sposób:

form_for [:admin, @user] do |f| ... end
Parametry z formularza będą dostępne pod params[:user], a wygenerowana ścieżka to new_admin_user_path (przy nowym obiekcie), która powinna trafić do Twojego kontrolera w katalogu admin/users_controller.rb

Namespace dla modeli nie jest polecaną rzeczą:
http://m.onkey.org/2007/12/9/namespaced-models

Wieczorem (po pracy) sprawdze obydwie podpowiedzi. Mam nadzieje, ze uda się. Dzieki za nieocenioną pomoc.
No i czekam na jakieś dalsz propozycje… Moze inaczej rozwiązać problem z panelem admina… Ma ktoś jakieś pomysły?

wlasnie zauwazylem dziwną rzecz… oczywiscie użyłem przez Was podanych sposobów, ale dalej wyskakiwal mi SystemStackError : stack level to deep. Zostałem jednak przy metodzie podanej przez morgoth.
Metodą usuwania częsci kodu i sprawdzania, doszedlem, ze wszystko psuje sie przez accessors methods w modelu User - gdy probuje przeciazyc przypisanie hasla

def password=(pwd) self.password = Digest::SHA1.hexdigest(pwd) end
załączone jest oczywiscie require ‘digest/sha1’
Gdy tylko usunalem te metody (password i parrword=) wszystko zaczelo cacy dzialac. Dziwna sprawa i nie wiem co moze oznaczac ten blad. Czy railsy nie pozwalaja z kontolera z przestrzenia nazw na korzystanie z takich metod w modelach?

Wpadłeś po prostu w pętlę. Fragment:

self.password = Digest::SHA1.hexdigest(pwd)

Wywoływał funckję password= czyli samą siebie. W kółko.

Jeśli chcesz zakodować hasło przy zapisie, możesz skorzystać z:

[quote=pix]def password=(arg) self.password=arg end
[/quote]
Faktycznie, bardzo ciekawe skąd miałeś “stack level too deep” :wink:
Weź pogooglaj skąd się bierze ten błąd albo dokładnie przeanalizuj co robi ten kod. A najlepiej jedno i drugie.

EDIT: Daaamn, Olek, zepsułeś całą wartość dydaktyczną wątku! :stuck_out_tongue:

Oszust ze mnie: podpowiadam przy rozwiązywaniu zagadek. :wink:
EDIT: Spokojnie, jeszcze będą pytania, czemu przy updejcie zmienia się hasło przy korzystaniu z callbacków. :slight_smile:

Podłączę się do tematu: nie mieliście żadnych problemów z używaniem modeli znajdujących się w osobnej przestrzeni nazw? Bezproblemowo działa to u nas tylko w przypadku STI, gdzieś znaleźliśmy, że nawet team Railsów odradza używanie namespace-ów w modelach.

i tu wlasnie saba pogrzebany…
Zastosowalem się do Waszych pomysłów i wszystko dziala cacy :slight_smile: Nie wpadlem na ten blad na poczatku… ;/ Tak to jest jak sie bezmyslnie przepisuje z roznych projektow ;]

Dzieki za pomoc. Piwo dla panów barman! :wink:

Skoro ma być dydaktycznie to dorzucę swoje trzy grosze. Jeśli zamierzasz robić duża aplikację, w której wymogi bezpieczeństwa są istotne, to zdecydowanie lepiej napisać ją jako osobną i umieścić pod inną domeną, np. admin.twojaaplikacja.com, zabezpieczyć logowanie przez SSL dodatkowo tylko z wybranych ip lub z wykorzystaniem certyfikatów SSL klienta.

Masz wtedy znacznie większą pewność, że wrażliwe funkcje systemu są dobrze zabezpieczone: w szczególności znacznie trudniej jest przejąć sesję administratora.

Oczywiście, skoro mowa o bezpieczeństwie to warto poczytać Security Guide lub jego tłumaczenie (oparte na troszkę starszej wersji przewodnika).

Że się wtrące: A co z synchronizacją modeli wtedy (szczególnie relacji) pomiędzy takimi dwoma projektami? Warto je uwspólniać jakoś (symlink cyz coś) zgodnie z DRY czy wręcz przeciwnie?

Wspólna baza :wink:

chodzi mi o modele, ActiveRecord - chyba to jeszcze jest wspólne. Wszak kontrolery administracyjne zarzadzaja tym co jest po stronie “klientów” widdoczne.

Tak, też myślałem o tych modelach. Nie pamiętam jakie było zalecenie w artykule dot. bezpieczeństwa (gdzieś to czytałem, ale nie pamiętam dokładnie gdzie), natomiast przychodzą mi do głowy dwa rozwiązania:

  1. Eksportowanie modeli w gemie i zasysanie ich w projekcie panelu administracyjnego
  2. Przerzucenie problemu na SCM (w svn było coś takiego jak external, w gicie jeszcze nie natknąłem się na jego odpowiednik).

W każdym razie symlinka z pewnością bym nie polecał.

Przez chwilę myślałem, że mogłyby być zupełnie oddzielne (model dla admina nie ma zbyt rozbudowanej logiki biznesowej), ale prędzej, czy później zrobiłby się bałagan. Chociażby samo przepisywanie związków między modelami byłoby duplikowane. Najważniejsze z p. widzenia bezpieczeństwa są widoki oraz kontrolery - dlatego powinny być rozdzielona. Poza tym jako panel admina można zastosować jakieś gotowe rozwiązanie, np. ActiveScaffold, więc z tym i tak nie ma zbyt wiele pracy.